Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
09092a78
Commit
09092a78
authored
Apr 27, 2011
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cgo: handle versioned ELF symbols
Fixes #1397. R=iant CC=golang-dev
https://golang.org/cl/4444064
parent
70b0de8e
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
451 additions
and
116 deletions
+451
-116
src/cmd/5l/l.h
src/cmd/5l/l.h
+1
-0
src/cmd/6l/asm.c
src/cmd/6l/asm.c
+37
-2
src/cmd/6l/l.h
src/cmd/6l/l.h
+1
-0
src/cmd/8l/asm.c
src/cmd/8l/asm.c
+37
-3
src/cmd/8l/l.h
src/cmd/8l/l.h
+1
-0
src/cmd/cc/dpchk.c
src/cmd/cc/dpchk.c
+28
-2
src/cmd/cc/macbody
src/cmd/cc/macbody
+1
-1
src/cmd/cgo/main.go
src/cmd/cgo/main.go
+1
-15
src/cmd/cgo/out.go
src/cmd/cgo/out.go
+47
-26
src/cmd/ld/elf.c
src/cmd/ld/elf.c
+117
-18
src/cmd/ld/elf.h
src/cmd/ld/elf.h
+9
-0
src/cmd/ld/go.c
src/cmd/ld/go.c
+5
-1
src/pkg/debug/elf/elf.go
src/pkg/debug/elf/elf.go
+41
-24
src/pkg/debug/elf/file.go
src/pkg/debug/elf/file.go
+125
-24
No files found.
src/cmd/5l/l.h
View file @
09092a78
...
...
@@ -156,6 +156,7 @@ struct Sym
char
*
file
;
char
*
dynimpname
;
char
*
dynimplib
;
char
*
dynimpvers
;
// STEXT
Auto
*
autom
;
...
...
src/cmd/6l/asm.c
View file @
09092a78
...
...
@@ -95,6 +95,8 @@ enum {
ElfStrStrtab
,
ElfStrRelaPlt
,
ElfStrPlt
,
ElfStrGnuVersion
,
ElfStrGnuVersionR
,
NElfStr
};
...
...
@@ -436,6 +438,7 @@ adddynsym(Sym *s)
s
->
dynid
=
nelfsym
++
;
d
=
lookup
(
".dynsym"
,
0
);
name
=
s
->
dynimpname
;
if
(
name
==
nil
)
name
=
s
->
name
;
...
...
@@ -586,6 +589,8 @@ doelf(void)
elfstr
[
ElfStrRela
]
=
addstring
(
shstrtab
,
".rela"
);
elfstr
[
ElfStrRelaPlt
]
=
addstring
(
shstrtab
,
".rela.plt"
);
elfstr
[
ElfStrPlt
]
=
addstring
(
shstrtab
,
".plt"
);
elfstr
[
ElfStrGnuVersion
]
=
addstring
(
shstrtab
,
".gnu.version"
);
elfstr
[
ElfStrGnuVersionR
]
=
addstring
(
shstrtab
,
".gnu.version_r"
);
/* dynamic symbol table - first entry all zeros */
s
=
lookup
(
".dynsym"
,
0
);
...
...
@@ -629,6 +634,14 @@ doelf(void)
s
=
lookup
(
".rela.plt"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
s
=
lookup
(
".gnu.version"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
s
=
lookup
(
".gnu.version_r"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
/* define dynamic elf table */
s
=
lookup
(
".dynamic"
,
0
);
...
...
@@ -653,7 +666,8 @@ doelf(void)
elfwritedynent
(
s
,
DT_PLTREL
,
DT_RELA
);
elfwritedynentsymsize
(
s
,
DT_PLTRELSZ
,
lookup
(
".rela.plt"
,
0
));
elfwritedynentsym
(
s
,
DT_JMPREL
,
lookup
(
".rela.plt"
,
0
));
elfwritedynent
(
s
,
DT_NULL
,
0
);
// Do not write DT_NULL. elfdynhash will finish it.
}
}
...
...
@@ -735,8 +749,11 @@ asmb(void)
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
elftextsh
=
1
;
if
(
!
debug
[
'd'
])
if
(
!
debug
[
'd'
])
{
elftextsh
+=
10
;
if
(
elfverneed
)
elftextsh
+=
2
;
}
break
;
case
Hwindows
:
break
;
...
...
@@ -920,6 +937,24 @@ asmb(void)
sh
->
addralign
=
1
;
shsym
(
sh
,
lookup
(
".dynstr"
,
0
));
if
(
elfverneed
)
{
sh
=
newElfShdr
(
elfstr
[
ElfStrGnuVersion
]);
sh
->
type
=
SHT_GNU_VERSYM
;
sh
->
flags
=
SHF_ALLOC
;
sh
->
addralign
=
2
;
sh
->
link
=
dynsym
;
sh
->
entsize
=
2
;
shsym
(
sh
,
lookup
(
".gnu.version"
,
0
));
sh
=
newElfShdr
(
elfstr
[
ElfStrGnuVersionR
]);
sh
->
type
=
SHT_GNU_VERNEED
;
sh
->
flags
=
SHF_ALLOC
;
sh
->
addralign
=
8
;
sh
->
info
=
elfverneed
;
sh
->
link
=
dynsym
+
1
;
// dynstr
shsym
(
sh
,
lookup
(
".gnu.version_r"
,
0
));
}
sh
=
newElfShdr
(
elfstr
[
ElfStrRelaPlt
]);
sh
->
type
=
SHT_RELA
;
sh
->
flags
=
SHF_ALLOC
;
...
...
src/cmd/6l/l.h
View file @
09092a78
...
...
@@ -148,6 +148,7 @@ struct Sym
char
*
file
;
char
*
dynimpname
;
char
*
dynimplib
;
char
*
dynimpvers
;
// STEXT
Auto
*
autom
;
...
...
src/cmd/8l/asm.c
View file @
09092a78
...
...
@@ -91,6 +91,8 @@ enum {
ElfStrStrtab
,
ElfStrRelPlt
,
ElfStrPlt
,
ElfStrGnuVersion
,
ElfStrGnuVersionR
,
NElfStr
};
...
...
@@ -420,7 +422,7 @@ adddynsym(Sym *s)
s
->
dynid
=
nelfsym
++
;
d
=
lookup
(
".dynsym"
,
0
);
/* name */
name
=
s
->
dynimpname
;
if
(
name
==
nil
)
...
...
@@ -545,6 +547,8 @@ doelf(void)
elfstr
[
ElfStrRel
]
=
addstring
(
shstrtab
,
".rel"
);
elfstr
[
ElfStrRelPlt
]
=
addstring
(
shstrtab
,
".rel.plt"
);
elfstr
[
ElfStrPlt
]
=
addstring
(
shstrtab
,
".plt"
);
elfstr
[
ElfStrGnuVersion
]
=
addstring
(
shstrtab
,
".gnu.version"
);
elfstr
[
ElfStrGnuVersionR
]
=
addstring
(
shstrtab
,
".gnu.version_r"
);
/* interpreter string */
s
=
lookup
(
".interp"
,
0
);
...
...
@@ -592,6 +596,14 @@ doelf(void)
s
=
lookup
(
".rel.plt"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
s
=
lookup
(
".gnu.version"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
s
=
lookup
(
".gnu.version_r"
,
0
);
s
->
reachable
=
1
;
s
->
type
=
SELFDATA
;
elfsetupplt
();
...
...
@@ -617,7 +629,8 @@ doelf(void)
elfwritedynent
(
s
,
DT_PLTREL
,
DT_REL
);
elfwritedynentsymsize
(
s
,
DT_PLTRELSZ
,
lookup
(
".rel.plt"
,
0
));
elfwritedynentsym
(
s
,
DT_JMPREL
,
lookup
(
".rel.plt"
,
0
));
elfwritedynent
(
s
,
DT_NULL
,
0
);
// Do not write DT_NULL. elfdynhash will finish it.
}
}
...
...
@@ -681,8 +694,11 @@ asmb(void)
/* index of elf text section; needed by asmelfsym, double-checked below */
/* !debug['d'] causes extra sections before the .text section */
elftextsh
=
1
;
if
(
!
debug
[
'd'
])
if
(
!
debug
[
'd'
])
{
elftextsh
+=
10
;
if
(
elfverneed
)
elftextsh
+=
2
;
}
}
symsize
=
0
;
...
...
@@ -966,6 +982,24 @@ asmb(void)
sh
->
addralign
=
1
;
shsym
(
sh
,
lookup
(
".dynstr"
,
0
));
if
(
elfverneed
)
{
sh
=
newElfShdr
(
elfstr
[
ElfStrGnuVersion
]);
sh
->
type
=
SHT_GNU_VERSYM
;
sh
->
flags
=
SHF_ALLOC
;
sh
->
addralign
=
2
;
sh
->
link
=
dynsym
;
sh
->
entsize
=
2
;
shsym
(
sh
,
lookup
(
".gnu.version"
,
0
));
sh
=
newElfShdr
(
elfstr
[
ElfStrGnuVersionR
]);
sh
->
type
=
SHT_GNU_VERNEED
;
sh
->
flags
=
SHF_ALLOC
;
sh
->
addralign
=
4
;
sh
->
info
=
elfverneed
;
sh
->
link
=
dynsym
+
1
;
// dynstr
shsym
(
sh
,
lookup
(
".gnu.version_r"
,
0
));
}
sh
=
newElfShdr
(
elfstr
[
ElfStrRelPlt
]);
sh
->
type
=
SHT_REL
;
sh
->
flags
=
SHF_ALLOC
;
...
...
src/cmd/8l/l.h
View file @
09092a78
...
...
@@ -147,6 +147,7 @@ struct Sym
char
*
file
;
char
*
dynimpname
;
char
*
dynimplib
;
char
*
dynimpvers
;
// STEXT
Auto
*
autom
;
...
...
src/cmd/cc/dpchk.c
View file @
09092a78
...
...
@@ -534,6 +534,32 @@ out:
print
(
"%s incomplete
\n
"
,
s
->
name
);
}
Sym
*
getimpsym
(
void
)
{
int
c
;
char
*
cp
;
c
=
getnsc
();
if
(
isspace
(
c
)
||
c
==
'"'
)
{
unget
(
c
);
return
S
;
}
for
(
cp
=
symb
;;)
{
if
(
cp
<=
symb
+
NSYMB
-
4
)
*
cp
++
=
c
;
c
=
getc
();
if
(
c
>
0
&&
!
isspace
(
c
)
&&
c
!=
'"'
)
continue
;
unget
(
c
);
break
;
}
*
cp
=
0
;
if
(
cp
>
symb
+
NSYMB
-
4
)
yyerror
(
"symbol too large: %s"
,
symb
);
return
lookup
();
}
void
pragdynimport
(
void
)
{
...
...
@@ -541,11 +567,11 @@ pragdynimport(void)
char
*
path
;
Dynimp
*
f
;
local
=
getsym
();
local
=
get
imp
sym
();
if
(
local
==
nil
)
goto
err
;
remote
=
getsym
();
remote
=
get
imp
sym
();
if
(
remote
==
nil
)
goto
err
;
...
...
src/cmd/cc/macbody
View file @
09092a78
...
...
@@ -63,7 +63,7 @@ getsym(void)
if(cp <= symb+NSYMB-4)
*cp++ = c;
c = getc();
if(isalnum(c) || c == '_' || c >= 0x80
|| c == '$'
)
if(isalnum(c) || c == '_' || c >= 0x80)
continue;
unget(c);
break;
...
...
src/cmd/cgo/main.go
View file @
09092a78
...
...
@@ -20,7 +20,6 @@ import (
"os"
"reflect"
"strings"
"runtime"
)
// A Package collects information about the package we're going to write.
...
...
@@ -135,20 +134,7 @@ func main() {
// instead of needing to make the linkers duplicate all the
// specialized knowledge gcc has about where to look for imported
// symbols and which ones to use.
syms
,
imports
:=
dynimport
(
*
dynobj
)
if
runtime
.
GOOS
==
"windows"
{
for
_
,
sym
:=
range
syms
{
ss
:=
strings
.
Split
(
sym
,
":"
,
-
1
)
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
ss
[
0
],
ss
[
0
],
strings
.
ToLower
(
ss
[
1
]))
}
return
}
for
_
,
sym
:=
range
syms
{
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
sym
,
sym
,
""
)
}
for
_
,
p
:=
range
imports
{
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
"_"
,
"_"
,
p
)
}
dynimport
(
*
dynobj
)
return
}
...
...
src/cmd/cgo/out.go
View file @
09092a78
...
...
@@ -95,42 +95,63 @@ func (p *Package) writeDefs() {
fc
.
Close
()
}
func
dynimport
(
obj
string
)
(
syms
,
imports
[]
string
)
{
var
f
interface
{
ImportedLibraries
()
([]
string
,
os
.
Error
)
ImportedSymbols
()
([]
string
,
os
.
Error
)
}
var
isMacho
bool
var
err1
,
err2
,
err3
os
.
Error
if
f
,
err1
=
elf
.
Open
(
obj
);
err1
!=
nil
{
if
f
,
err2
=
pe
.
Open
(
obj
);
err2
!=
nil
{
if
f
,
err3
=
macho
.
Open
(
obj
);
err3
!=
nil
{
fatalf
(
"cannot parse %s as ELF (%v) or PE (%v) or Mach-O (%v)"
,
obj
,
err1
,
err2
,
err3
)
func
dynimport
(
obj
string
)
{
if
f
,
err
:=
elf
.
Open
(
obj
);
err
==
nil
{
sym
,
err
:=
f
.
ImportedSymbols
()
if
err
!=
nil
{
fatalf
(
"cannot load imported symbols from ELF file %s: %v"
,
obj
,
err
)
}
for
_
,
s
:=
range
sym
{
targ
:=
s
.
Name
if
s
.
Version
!=
""
{
targ
+=
"@"
+
s
.
Version
}
isMacho
=
true
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
s
.
Name
,
targ
,
s
.
Library
)
}
lib
,
err
:=
f
.
ImportedLibraries
()
if
err
!=
nil
{
fatalf
(
"cannot load imported libraries from ELF file %s: %v"
,
obj
,
err
)
}
for
_
,
l
:=
range
lib
{
fmt
.
Printf
(
"#pragma dynimport _ _ %q
\n
"
,
l
)
}
return
}
var
err
os
.
Error
syms
,
err
=
f
.
ImportedSymbols
()
if
err
!=
nil
{
fatalf
(
"cannot load dynamic symbols: %v"
,
err
)
}
if
isMacho
{
// remove leading _ that OS X insists on
for
i
,
s
:=
range
syms
{
if
len
(
s
)
>=
2
&&
s
[
0
]
==
'_'
{
syms
[
i
]
=
s
[
1
:
]
if
f
,
err
:=
macho
.
Open
(
obj
);
err
==
nil
{
sym
,
err
:=
f
.
ImportedSymbols
()
if
err
!=
nil
{
fatalf
(
"cannot load imported symbols from Mach-O file %s: %v"
,
obj
,
err
)
}
for
_
,
s
:=
range
sym
{
if
len
(
s
)
>
0
&&
s
[
0
]
==
'_'
{
s
=
s
[
1
:
]
}
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
s
,
s
,
""
)
}
lib
,
err
:=
f
.
ImportedLibraries
()
if
err
!=
nil
{
fatalf
(
"cannot load imported libraries from Mach-O file %s: %v"
,
obj
,
err
)
}
for
_
,
l
:=
range
lib
{
fmt
.
Printf
(
"#pragma dynimport _ _ %q
\n
"
,
l
)
}
return
}
imports
,
err
=
f
.
ImportedLibraries
()
if
err
!=
nil
{
fatalf
(
"cannot load dynamic imports: %v"
,
err
)
if
f
,
err
:=
pe
.
Open
(
obj
);
err
==
nil
{
sym
,
err
:=
f
.
ImportedSymbols
()
if
err
!=
nil
{
fatalf
(
"cannot load imported symbols from PE file %s: v"
,
obj
,
err
)
}
for
_
,
s
:=
range
sym
{
ss
:=
strings
.
Split
(
s
,
":"
,
-
1
)
fmt
.
Printf
(
"#pragma dynimport %s %s %q
\n
"
,
ss
[
0
],
ss
[
0
],
strings
.
ToLower
(
ss
[
1
]))
}
return
}
return
fatalf
(
"cannot parse %s as ELF, Mach-O or PE"
,
obj
)
}
// Construct a gcc struct matching the 6c argument frame.
...
...
src/cmd/ld/elf.c
View file @
09092a78
...
...
@@ -331,17 +331,62 @@ elfinterp(ElfShdr *sh, uint64 startva, char *p)
}
extern
int
nelfsym
;
int
elfverneed
;
typedef
struct
Elfaux
Elfaux
;
typedef
struct
Elflib
Elflib
;
struct
Elflib
{
Elflib
*
next
;
Elfaux
*
aux
;
char
*
file
;
};
struct
Elfaux
{
Elfaux
*
next
;
int
num
;
char
*
vers
;
};
Elfaux
*
addelflib
(
Elflib
**
list
,
char
*
file
,
char
*
vers
)
{
Elflib
*
lib
;
Elfaux
*
aux
;
for
(
lib
=*
list
;
lib
;
lib
=
lib
->
next
)
if
(
strcmp
(
lib
->
file
,
file
)
==
0
)
goto
havelib
;
lib
=
mal
(
sizeof
*
lib
);
lib
->
next
=
*
list
;
lib
->
file
=
file
;
*
list
=
lib
;
havelib:
for
(
aux
=
lib
->
aux
;
aux
;
aux
=
aux
->
next
)
if
(
strcmp
(
aux
->
vers
,
vers
)
==
0
)
goto
haveaux
;
aux
=
mal
(
sizeof
*
aux
);
aux
->
next
=
lib
->
aux
;
aux
->
vers
=
vers
;
lib
->
aux
=
aux
;
haveaux:
return
aux
;
}
void
elfdynhash
(
void
)
{
Sym
*
s
,
*
sy
;
int
i
,
nbucket
,
b
;
uchar
*
pc
;
uint32
hc
,
g
;
uint32
*
chain
,
*
buckets
;
Sym
*
s
,
*
sy
,
*
dynstr
;
int
i
,
j
,
nbucket
,
b
,
nfile
;
uint32
hc
,
*
chain
,
*
buckets
;
int
nsym
;
char
*
name
;
Elfaux
**
need
;
Elflib
*
needlib
;
Elflib
*
l
;
Elfaux
*
x
;
if
(
!
iself
)
return
;
...
...
@@ -358,29 +403,29 @@ elfdynhash(void)
i
>>=
1
;
}
chain
=
malloc
(
nsym
*
sizeof
(
uint32
));
buckets
=
malloc
(
nbucket
*
sizeof
(
uint32
));
if
(
chain
==
nil
||
buckets
==
nil
)
{
needlib
=
nil
;
need
=
malloc
(
nsym
*
sizeof
need
[
0
]);
chain
=
malloc
(
nsym
*
sizeof
chain
[
0
]);
buckets
=
malloc
(
nbucket
*
sizeof
buckets
[
0
]);
if
(
need
==
nil
||
chain
==
nil
||
buckets
==
nil
)
{
cursym
=
nil
;
diag
(
"out of memory"
);
errorexit
();
}
memset
(
chain
,
0
,
nsym
*
sizeof
(
uint32
));
memset
(
buckets
,
0
,
nbucket
*
sizeof
(
uint32
));
memset
(
need
,
0
,
nsym
*
sizeof
need
[
0
]);
memset
(
chain
,
0
,
nsym
*
sizeof
chain
[
0
]);
memset
(
buckets
,
0
,
nbucket
*
sizeof
buckets
[
0
]);
for
(
sy
=
allsym
;
sy
!=
S
;
sy
=
sy
->
allsym
)
{
if
(
sy
->
dynid
<=
0
)
continue
;
hc
=
0
;
if
(
sy
->
dynimpvers
)
need
[
sy
->
dynid
]
=
addelflib
(
&
needlib
,
sy
->
dynimplib
,
sy
->
dynimpvers
);
name
=
sy
->
dynimpname
;
if
(
name
==
nil
)
name
=
sy
->
name
;
for
(
pc
=
(
uchar
*
)
name
;
*
pc
;
pc
++
)
{
hc
=
(
hc
<<
4
)
+
*
pc
;
g
=
hc
&
0xf0000000
;
hc
^=
g
>>
24
;
hc
&=
~
g
;
}
hc
=
elfhash
((
uchar
*
)
name
);
b
=
hc
%
nbucket
;
chain
[
sy
->
dynid
]
=
buckets
[
b
];
...
...
@@ -396,8 +441,62 @@ elfdynhash(void)
free
(
chain
);
free
(
buckets
);
// version symbols
dynstr
=
lookup
(
".dynstr"
,
0
);
s
=
lookup
(
".gnu.version_r"
,
0
);
i
=
2
;
nfile
=
0
;
for
(
l
=
needlib
;
l
;
l
=
l
->
next
)
{
nfile
++
;
// header
adduint16
(
s
,
1
);
// table version
j
=
0
;
for
(
x
=
l
->
aux
;
x
;
x
=
x
->
next
)
j
++
;
adduint16
(
s
,
j
);
// aux count
adduint32
(
s
,
addstring
(
dynstr
,
l
->
file
));
// file string offset
adduint32
(
s
,
16
);
// offset from header to first aux
if
(
l
->
next
)
adduint32
(
s
,
16
+
j
*
16
);
// offset from this header to next
else
adduint32
(
s
,
0
);
for
(
x
=
l
->
aux
;
x
;
x
=
x
->
next
)
{
x
->
num
=
i
++
;
// aux struct
adduint32
(
s
,
elfhash
((
uchar
*
)
x
->
vers
));
// hash
adduint16
(
s
,
0
);
// flags
adduint16
(
s
,
x
->
num
);
// other - index we refer to this by
adduint32
(
s
,
addstring
(
dynstr
,
x
->
vers
));
// version string offset
if
(
x
->
next
)
adduint32
(
s
,
16
);
// offset from this aux to next
else
adduint32
(
s
,
0
);
}
}
// version references
s
=
lookup
(
".gnu.version"
,
0
);
for
(
i
=
0
;
i
<
nsym
;
i
++
)
{
if
(
i
==
0
)
adduint16
(
s
,
0
);
// first entry - no symbol
else
if
(
need
[
i
]
==
nil
)
adduint16
(
s
,
1
);
// global
else
adduint16
(
s
,
need
[
i
]
->
num
);
}
elfwritedynent
(
lookup
(
".dynamic"
,
0
),
DT_NULL
,
0
);
free
(
need
);
s
=
lookup
(
".dynamic"
,
0
);
elfverneed
=
nfile
;
if
(
elfverneed
)
{
elfwritedynentsym
(
s
,
DT_VERNEED
,
lookup
(
".gnu.version_r"
,
0
));
elfwritedynent
(
s
,
DT_VERNEEDNUM
,
nfile
);
elfwritedynentsym
(
s
,
DT_VERSYM
,
lookup
(
".gnu.version"
,
0
));
}
elfwritedynent
(
s
,
DT_NULL
,
0
);
}
ElfPhdr
*
...
...
src/cmd/ld/elf.h
View file @
09092a78
...
...
@@ -216,6 +216,9 @@ typedef struct {
#define SHT_SYMTAB_SHNDX 18
/* Section indexes (see SHN_XINDEX). */
#define SHT_LOOS 0x60000000
/* First of OS specific semantics */
#define SHT_HIOS 0x6fffffff
/* Last of OS specific semantics */
#define SHT_GNU_VERDEF 0x6ffffffd
#define SHT_GNU_VERNEED 0x6ffffffe
#define SHT_GNU_VERSYM 0x6fffffff
#define SHT_LOPROC 0x70000000
/* reserved range for processor */
#define SHT_HIPROC 0x7fffffff
/* specific section header types */
#define SHT_LOUSER 0x80000000
/* reserved range for application */
...
...
@@ -311,6 +314,10 @@ typedef struct {
#define DT_LOPROC 0x70000000
/* First processor-specific type. */
#define DT_HIPROC 0x7fffffff
/* Last processor-specific type. */
#define DT_VERNEED 0x6ffffffe
#define DT_VERNEEDNUM 0x6fffffff
#define DT_VERSYM 0x6ffffff0
/* Values for DT_FLAGS */
#define DF_ORIGIN 0x0001
/* Indicates that the object being loaded may
make reference to the $ORIGIN substitution
...
...
@@ -962,12 +969,14 @@ uint64 endelf(void);
extern
int
numelfphdr
;
extern
int
numelfshdr
;
extern
int
iself
;
extern
int
elfverneed
;
int
elfwriteinterp
(
void
);
void
elfinterp
(
ElfShdr
*
,
uint64
,
char
*
);
void
elfdynhash
(
void
);
ElfPhdr
*
elfphload
(
Segment
*
);
ElfShdr
*
elfshbits
(
Section
*
);
void
elfsetstring
(
char
*
,
int
);
void
elfaddverneed
(
Sym
*
);
/*
* Total amount of space to reserve at the start of the file
...
...
src/cmd/ld/go.c
View file @
09092a78
...
...
@@ -412,7 +412,7 @@ parsemethod(char **pp, char *ep, char **methp)
static
void
loaddynimport
(
char
*
file
,
char
*
pkg
,
char
*
p
,
int
n
)
{
char
*
pend
,
*
next
,
*
name
,
*
def
,
*
p0
,
*
lib
;
char
*
pend
,
*
next
,
*
name
,
*
def
,
*
p0
,
*
lib
,
*
q
;
Sym
*
s
;
pend
=
p
+
n
;
...
...
@@ -459,10 +459,14 @@ loaddynimport(char *file, char *pkg, char *p, int n)
}
name
=
expandpkg
(
name
,
pkg
);
q
=
strchr
(
def
,
'@'
);
if
(
q
)
*
q
++
=
'\0'
;
s
=
lookup
(
name
,
0
);
if
(
s
->
type
==
0
||
s
->
type
==
SXREF
)
{
s
->
dynimplib
=
lib
;
s
->
dynimpname
=
def
;
s
->
dynimpvers
=
q
;
s
->
type
=
SDYNIMPORT
;
}
}
...
...
src/pkg/debug/elf/elf.go
View file @
09092a78
...
...
@@ -330,29 +330,35 @@ func (i SectionIndex) GoString() string { return stringName(uint32(i), shnString
type
SectionType
uint32
const
(
SHT_NULL
SectionType
=
0
/* inactive */
SHT_PROGBITS
SectionType
=
1
/* program defined information */
SHT_SYMTAB
SectionType
=
2
/* symbol table section */
SHT_STRTAB
SectionType
=
3
/* string table section */
SHT_RELA
SectionType
=
4
/* relocation section with addends */
SHT_HASH
SectionType
=
5
/* symbol hash table section */
SHT_DYNAMIC
SectionType
=
6
/* dynamic section */
SHT_NOTE
SectionType
=
7
/* note section */
SHT_NOBITS
SectionType
=
8
/* no space section */
SHT_REL
SectionType
=
9
/* relocation section - no addends */
SHT_SHLIB
SectionType
=
10
/* reserved - purpose unknown */
SHT_DYNSYM
SectionType
=
11
/* dynamic symbol table section */
SHT_INIT_ARRAY
SectionType
=
14
/* Initialization function pointers. */
SHT_FINI_ARRAY
SectionType
=
15
/* Termination function pointers. */
SHT_PREINIT_ARRAY
SectionType
=
16
/* Pre-initialization function ptrs. */
SHT_GROUP
SectionType
=
17
/* Section group. */
SHT_SYMTAB_SHNDX
SectionType
=
18
/* Section indexes (see SHN_XINDEX). */
SHT_LOOS
SectionType
=
0x60000000
/* First of OS specific semantics */
SHT_HIOS
SectionType
=
0x6fffffff
/* Last of OS specific semantics */
SHT_LOPROC
SectionType
=
0x70000000
/* reserved range for processor */
SHT_HIPROC
SectionType
=
0x7fffffff
/* specific section header types */
SHT_LOUSER
SectionType
=
0x80000000
/* reserved range for application */
SHT_HIUSER
SectionType
=
0xffffffff
/* specific indexes */
SHT_NULL
SectionType
=
0
/* inactive */
SHT_PROGBITS
SectionType
=
1
/* program defined information */
SHT_SYMTAB
SectionType
=
2
/* symbol table section */
SHT_STRTAB
SectionType
=
3
/* string table section */
SHT_RELA
SectionType
=
4
/* relocation section with addends */
SHT_HASH
SectionType
=
5
/* symbol hash table section */
SHT_DYNAMIC
SectionType
=
6
/* dynamic section */
SHT_NOTE
SectionType
=
7
/* note section */
SHT_NOBITS
SectionType
=
8
/* no space section */
SHT_REL
SectionType
=
9
/* relocation section - no addends */
SHT_SHLIB
SectionType
=
10
/* reserved - purpose unknown */
SHT_DYNSYM
SectionType
=
11
/* dynamic symbol table section */
SHT_INIT_ARRAY
SectionType
=
14
/* Initialization function pointers. */
SHT_FINI_ARRAY
SectionType
=
15
/* Termination function pointers. */
SHT_PREINIT_ARRAY
SectionType
=
16
/* Pre-initialization function ptrs. */
SHT_GROUP
SectionType
=
17
/* Section group. */
SHT_SYMTAB_SHNDX
SectionType
=
18
/* Section indexes (see SHN_XINDEX). */
SHT_LOOS
SectionType
=
0x60000000
/* First of OS specific semantics */
SHT_GNU_ATTRIBUTES
SectionType
=
0x6ffffff5
/* GNU object attributes */
SHT_GNU_HASH
SectionType
=
0x6ffffff6
/* GNU hash table */
SHT_GNU_LIBLIST
SectionType
=
0x6ffffff7
/* GNU prelink library list */
SHT_GNU_VERDEF
SectionType
=
0x6ffffffd
/* GNU version definition section */
SHT_GNU_VERNEED
SectionType
=
0x6ffffffe
/* GNU version needs section */
SHT_GNU_VERSYM
SectionType
=
0x6fffffff
/* GNU version symbol table */
SHT_HIOS
SectionType
=
0x6fffffff
/* Last of OS specific semantics */
SHT_LOPROC
SectionType
=
0x70000000
/* reserved range for processor */
SHT_HIPROC
SectionType
=
0x7fffffff
/* specific section header types */
SHT_LOUSER
SectionType
=
0x80000000
/* reserved range for application */
SHT_HIUSER
SectionType
=
0xffffffff
/* specific indexes */
)
var
shtStrings
=
[]
intName
{
...
...
@@ -374,7 +380,12 @@ var shtStrings = []intName{
{
17
,
"SHT_GROUP"
},
{
18
,
"SHT_SYMTAB_SHNDX"
},
{
0x60000000
,
"SHT_LOOS"
},
{
0x6fffffff
,
"SHT_HIOS"
},
{
0x6ffffff5
,
"SHT_GNU_ATTRIBUTES"
},
{
0x6ffffff6
,
"SHT_GNU_HASH"
},
{
0x6ffffff7
,
"SHT_GNU_LIBLIST"
},
{
0x6ffffffd
,
"SHT_GNU_VERDEF"
},
{
0x6ffffffe
,
"SHT_GNU_VERNEED"
},
{
0x6fffffff
,
"SHT_GNU_VERSYM"
},
{
0x70000000
,
"SHT_LOPROC"
},
{
0x7fffffff
,
"SHT_HIPROC"
},
{
0x80000000
,
"SHT_LOUSER"
},
...
...
@@ -518,6 +529,9 @@ const (
DT_PREINIT_ARRAYSZ
DynTag
=
33
/* Size in bytes of the array of pre-initialization functions. */
DT_LOOS
DynTag
=
0x6000000d
/* First OS-specific */
DT_HIOS
DynTag
=
0x6ffff000
/* Last OS-specific */
DT_VERSYM
DynTag
=
0x6ffffff0
DT_VERNEED
DynTag
=
0x6ffffffe
DT_VERNEEDNUM
DynTag
=
0x6fffffff
DT_LOPROC
DynTag
=
0x70000000
/* First processor-specific type. */
DT_HIPROC
DynTag
=
0x7fffffff
/* Last processor-specific type. */
)
...
...
@@ -559,6 +573,9 @@ var dtStrings = []intName{
{
33
,
"DT_PREINIT_ARRAYSZ"
},
{
0x6000000d
,
"DT_LOOS"
},
{
0x6ffff000
,
"DT_HIOS"
},
{
0x6ffffff0
,
"DT_VERSYM"
},
{
0x6ffffffe
,
"DT_VERNEED"
},
{
0x6fffffff
,
"DT_VERNEEDNUM"
},
{
0x70000000
,
"DT_LOPROC"
},
{
0x7fffffff
,
"DT_HIPROC"
},
}
...
...
src/pkg/debug/elf/file.go
View file @
09092a78
...
...
@@ -35,9 +35,11 @@ type FileHeader struct {
// A File represents an open ELF file.
type
File
struct
{
FileHeader
Sections
[]
*
Section
Progs
[]
*
Prog
closer
io
.
Closer
Sections
[]
*
Section
Progs
[]
*
Prog
closer
io
.
Closer
gnuNeed
[]
verneed
gnuVersym
[]
byte
}
// A SectionHeader represents a single ELF section header.
...
...
@@ -329,8 +331,8 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
}
// getSymbols returns a slice of Symbols from parsing the symbol table
// with the given type.
func
(
f
*
File
)
getSymbols
(
typ
SectionType
)
([]
Symbol
,
os
.
Error
)
{
// with the given type
, along with the associated string table
.
func
(
f
*
File
)
getSymbols
(
typ
SectionType
)
([]
Symbol
,
[]
byte
,
os
.
Error
)
{
switch
f
.
Class
{
case
ELFCLASS64
:
return
f
.
getSymbols64
(
typ
)
...
...
@@ -339,27 +341,27 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
return
f
.
getSymbols32
(
typ
)
}
return
nil
,
os
.
ErrorString
(
"not implemented"
)
return
nil
,
nil
,
os
.
ErrorString
(
"not implemented"
)
}
func
(
f
*
File
)
getSymbols32
(
typ
SectionType
)
([]
Symbol
,
os
.
Error
)
{
func
(
f
*
File
)
getSymbols32
(
typ
SectionType
)
([]
Symbol
,
[]
byte
,
os
.
Error
)
{
symtabSection
:=
f
.
SectionByType
(
typ
)
if
symtabSection
==
nil
{
return
nil
,
os
.
ErrorString
(
"no symbol section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"no symbol section"
)
}
data
,
err
:=
symtabSection
.
Data
()
if
err
!=
nil
{
return
nil
,
os
.
ErrorString
(
"cannot load symbol section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"cannot load symbol section"
)
}
symtab
:=
bytes
.
NewBuffer
(
data
)
if
symtab
.
Len
()
%
Sym32Size
!=
0
{
return
nil
,
os
.
ErrorString
(
"length of symbol section is not a multiple of SymSize"
)
return
nil
,
nil
,
os
.
ErrorString
(
"length of symbol section is not a multiple of SymSize"
)
}
strdata
,
err
:=
f
.
stringTable
(
symtabSection
.
Link
)
if
err
!=
nil
{
return
nil
,
os
.
ErrorString
(
"cannot load string table section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"cannot load string table section"
)
}
// The first entry is all zeros.
...
...
@@ -382,27 +384,27 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
i
++
}
return
symbols
,
nil
return
symbols
,
strdata
,
nil
}
func
(
f
*
File
)
getSymbols64
(
typ
SectionType
)
([]
Symbol
,
os
.
Error
)
{
func
(
f
*
File
)
getSymbols64
(
typ
SectionType
)
([]
Symbol
,
[]
byte
,
os
.
Error
)
{
symtabSection
:=
f
.
SectionByType
(
typ
)
if
symtabSection
==
nil
{
return
nil
,
os
.
ErrorString
(
"no symbol section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"no symbol section"
)
}
data
,
err
:=
symtabSection
.
Data
()
if
err
!=
nil
{
return
nil
,
os
.
ErrorString
(
"cannot load symbol section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"cannot load symbol section"
)
}
symtab
:=
bytes
.
NewBuffer
(
data
)
if
symtab
.
Len
()
%
Sym64Size
!=
0
{
return
nil
,
os
.
ErrorString
(
"length of symbol section is not a multiple of Sym64Size"
)
return
nil
,
nil
,
os
.
ErrorString
(
"length of symbol section is not a multiple of Sym64Size"
)
}
strdata
,
err
:=
f
.
stringTable
(
symtabSection
.
Link
)
if
err
!=
nil
{
return
nil
,
os
.
ErrorString
(
"cannot load string table section"
)
return
nil
,
nil
,
os
.
ErrorString
(
"cannot load string table section"
)
}
// The first entry is all zeros.
...
...
@@ -425,7 +427,7 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
i
++
}
return
symbols
,
nil
return
symbols
,
strdata
,
nil
}
// getString extracts a string from an ELF string table.
...
...
@@ -468,7 +470,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
return
os
.
ErrorString
(
"length of relocation section is not a multiple of Sym64Size"
)
}
symbols
,
err
:=
f
.
getSymbols
(
SHT_SYMTAB
)
symbols
,
_
,
err
:=
f
.
getSymbols
(
SHT_SYMTAB
)
if
err
!=
nil
{
return
err
}
...
...
@@ -544,24 +546,123 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
return
dwarf
.
New
(
abbrev
,
nil
,
nil
,
info
,
nil
,
nil
,
nil
,
str
)
}
type
ImportedSymbol
struct
{
Name
string
Version
string
Library
string
}
// ImportedSymbols returns the names of all symbols
// referred to by the binary f that are expected to be
// satisfied by other libraries at dynamic load time.
// It does not return weak symbols.
func
(
f
*
File
)
ImportedSymbols
()
([]
string
,
os
.
Error
)
{
sym
,
err
:=
f
.
getSymbols
(
SHT_DYNSYM
)
func
(
f
*
File
)
ImportedSymbols
()
([]
ImportedSymbol
,
os
.
Error
)
{
sym
,
str
,
err
:=
f
.
getSymbols
(
SHT_DYNSYM
)
if
err
!=
nil
{
return
nil
,
err
}
var
all
[]
string
for
_
,
s
:=
range
sym
{
f
.
gnuVersionInit
(
str
)
var
all
[]
ImportedSymbol
for
i
,
s
:=
range
sym
{
if
ST_BIND
(
s
.
Info
)
==
STB_GLOBAL
&&
s
.
Section
==
SHN_UNDEF
{
all
=
append
(
all
,
s
.
Name
)
all
=
append
(
all
,
ImportedSymbol
{
Name
:
s
.
Name
})
f
.
gnuVersion
(
i
,
&
all
[
len
(
all
)
-
1
])
}
}
return
all
,
nil
}
type
verneed
struct
{
File
string
Name
string
}
// gnuVersionInit parses the GNU version tables
// for use by calls to gnuVersion.
func
(
f
*
File
)
gnuVersionInit
(
str
[]
byte
)
{
// Accumulate verneed information.
vn
:=
f
.
SectionByType
(
SHT_GNU_VERNEED
)
if
vn
==
nil
{
return
}
d
,
_
:=
vn
.
Data
()
var
need
[]
verneed
i
:=
0
for
{
if
i
+
16
>
len
(
d
)
{
break
}
vers
:=
f
.
ByteOrder
.
Uint16
(
d
[
i
:
i
+
2
])
if
vers
!=
1
{
break
}
cnt
:=
f
.
ByteOrder
.
Uint16
(
d
[
i
+
2
:
i
+
4
])
fileoff
:=
f
.
ByteOrder
.
Uint32
(
d
[
i
+
4
:
i
+
8
])
aux
:=
f
.
ByteOrder
.
Uint32
(
d
[
i
+
8
:
i
+
12
])
next
:=
f
.
ByteOrder
.
Uint32
(
d
[
i
+
12
:
i
+
16
])
file
,
_
:=
getString
(
str
,
int
(
fileoff
))
var
name
string
j
:=
i
+
int
(
aux
)
for
c
:=
0
;
c
<
int
(
cnt
);
c
++
{
if
j
+
16
>
len
(
d
)
{
break
}
// hash := f.ByteOrder.Uint32(d[j:j+4])
// flags := f.ByteOrder.Uint16(d[j+4:j+6])
other
:=
f
.
ByteOrder
.
Uint16
(
d
[
j
+
6
:
j
+
8
])
nameoff
:=
f
.
ByteOrder
.
Uint32
(
d
[
j
+
8
:
j
+
12
])
next
:=
f
.
ByteOrder
.
Uint32
(
d
[
j
+
12
:
j
+
16
])
name
,
_
=
getString
(
str
,
int
(
nameoff
))
ndx
:=
int
(
other
)
if
ndx
>=
len
(
need
)
{
a
:=
make
([]
verneed
,
2
*
(
ndx
+
1
))
copy
(
a
,
need
)
need
=
a
}
need
[
ndx
]
=
verneed
{
file
,
name
}
if
next
==
0
{
break
}
j
+=
int
(
next
)
}
if
next
==
0
{
break
}
i
+=
int
(
next
)
}
// Versym parallels symbol table, indexing into verneed.
vs
:=
f
.
SectionByType
(
SHT_GNU_VERSYM
)
if
vs
==
nil
{
return
}
d
,
_
=
vs
.
Data
()
f
.
gnuNeed
=
need
f
.
gnuVersym
=
d
}
// gnuVersion adds Library and Version information to sym,
// which came from offset i of the symbol table.
func
(
f
*
File
)
gnuVersion
(
i
int
,
sym
*
ImportedSymbol
)
{
// Each entry is two bytes; skip undef entry at beginning.
i
=
(
i
+
1
)
*
2
if
i
>=
len
(
f
.
gnuVersym
)
{
return
}
j
:=
int
(
f
.
ByteOrder
.
Uint16
(
f
.
gnuVersym
[
i
:
]))
if
j
<
2
||
j
>=
len
(
f
.
gnuNeed
)
{
return
}
n
:=
&
f
.
gnuNeed
[
j
]
sym
.
Library
=
n
.
File
sym
.
Version
=
n
.
Name
}
// ImportedLibraries returns the names of all libraries
// referred to by the binary f that are expected to be
// linked with the binary at dynamic link time.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment