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
4d8d6d5c
Commit
4d8d6d5c
authored
Dec 08, 2010
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ld: reading of ELF object files
R=iant CC=golang-dev
https://golang.org/cl/3507041
parent
7431a316
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
822 additions
and
0 deletions
+822
-0
src/cmd/ld/ldelf.c
src/cmd/ld/ldelf.c
+822
-0
No files found.
src/cmd/ld/ldelf.c
0 → 100644
View file @
4d8d6d5c
/*
Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
http://code.swtch.com/plan9port/src/tip/src/libmach/
Copyright © 2004 Russ Cox.
Portions Copyright © 2008-2010 Google Inc.
Portions Copyright © 2010 The Go Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "l.h"
#include "lib.h"
#include "../ld/elf.h"
enum
{
ElfClassNone
=
0
,
ElfClass32
,
ElfClass64
,
ElfDataNone
=
0
,
ElfDataLsb
,
ElfDataMsb
,
ElfTypeNone
=
0
,
ElfTypeRelocatable
,
ElfTypeExecutable
,
ElfTypeSharedObject
,
ElfTypeCore
,
/* 0xFF00 - 0xFFFF reserved for processor-specific types */
ElfMachNone
=
0
,
ElfMach32100
,
/* AT&T WE 32100 */
ElfMachSparc
,
/* SPARC */
ElfMach386
,
/* Intel 80386 */
ElfMach68000
,
/* Motorola 68000 */
ElfMach88000
,
/* Motorola 88000 */
ElfMach486
,
/* Intel 80486, no longer used */
ElfMach860
,
/* Intel 80860 */
ElfMachMips
,
/* MIPS RS3000 */
ElfMachS370
,
/* IBM System/370 */
ElfMachMipsLe
,
/* MIPS RS3000 LE */
ElfMachParisc
=
15
,
/* HP PA RISC */
ElfMachVpp500
=
17
,
/* Fujitsu VPP500 */
ElfMachSparc32Plus
,
/* SPARC V8+ */
ElfMach960
,
/* Intel 80960 */
ElfMachPower
,
/* PowerPC */
ElfMachPower64
,
/* PowerPC 64 */
ElfMachS390
,
/* IBM System/390 */
ElfMachV800
=
36
,
/* NEC V800 */
ElfMachFr20
,
/* Fujitsu FR20 */
ElfMachRh32
,
/* TRW RH-32 */
ElfMachRce
,
/* Motorola RCE */
ElfMachArm
,
/* ARM */
ElfMachAlpha
,
/* Digital Alpha */
ElfMachSH
,
/* Hitachi SH */
ElfMachSparc9
,
/* SPARC V9 */
ElfMachAmd64
=
62
,
/* and the list goes on... */
ElfAbiNone
=
0
,
ElfAbiSystemV
=
0
,
/* [sic] */
ElfAbiHPUX
,
ElfAbiNetBSD
,
ElfAbiLinux
,
ElfAbiSolaris
=
6
,
ElfAbiAix
,
ElfAbiIrix
,
ElfAbiFreeBSD
,
ElfAbiTru64
,
ElfAbiModesto
,
ElfAbiOpenBSD
,
ElfAbiARM
=
97
,
ElfAbiEmbedded
=
255
,
/* some of sections 0xFF00 - 0xFFFF reserved for various things */
ElfSectNone
=
0
,
ElfSectProgbits
,
ElfSectSymtab
,
ElfSectStrtab
,
ElfSectRela
,
ElfSectHash
,
ElfSectDynamic
,
ElfSectNote
,
ElfSectNobits
,
ElfSectRel
,
ElfSectShlib
,
ElfSectDynsym
,
ElfSectFlagWrite
=
0x1
,
ElfSectFlagAlloc
=
0x2
,
ElfSectFlagExec
=
0x4
,
/* 0xF0000000 are reserved for processor specific */
ElfSymBindLocal
=
0
,
ElfSymBindGlobal
,
ElfSymBindWeak
,
/* 13-15 reserved */
ElfSymTypeNone
=
0
,
ElfSymTypeObject
,
ElfSymTypeFunc
,
ElfSymTypeSection
,
ElfSymTypeFile
,
/* 13-15 reserved */
ElfSymShnNone
=
0
,
ElfSymShnAbs
=
0xFFF1
,
ElfSymShnCommon
=
0xFFF2
,
/* 0xFF00-0xFF1F reserved for processors */
/* 0xFF20-0xFF3F reserved for operating systems */
ElfProgNone
=
0
,
ElfProgLoad
,
ElfProgDynamic
,
ElfProgInterp
,
ElfProgNote
,
ElfProgShlib
,
ElfProgPhdr
,
ElfProgFlagExec
=
0x1
,
ElfProgFlagWrite
=
0x2
,
ElfProgFlagRead
=
0x4
,
ElfNotePrStatus
=
1
,
ElfNotePrFpreg
=
2
,
ElfNotePrPsinfo
=
3
,
ElfNotePrTaskstruct
=
4
,
ElfNotePrAuxv
=
6
,
ElfNotePrXfpreg
=
0x46e62b7f
/* for gdb/386 */
};
typedef
struct
ElfHdrBytes
ElfHdrBytes
;
typedef
struct
ElfSectBytes
ElfSectBytes
;
typedef
struct
ElfProgBytes
ElfProgBytes
;
typedef
struct
ElfSymBytes
ElfSymBytes
;
typedef
struct
ElfHdrBytes64
ElfHdrBytes64
;
typedef
struct
ElfSectBytes64
ElfSectBytes64
;
typedef
struct
ElfProgBytes64
ElfProgBytes64
;
typedef
struct
ElfSymBytes64
ElfSymBytes64
;
struct
ElfHdrBytes
{
uchar
ident
[
16
];
uchar
type
[
2
];
uchar
machine
[
2
];
uchar
version
[
4
];
uchar
entry
[
4
];
uchar
phoff
[
4
];
uchar
shoff
[
4
];
uchar
flags
[
4
];
uchar
ehsize
[
2
];
uchar
phentsize
[
2
];
uchar
phnum
[
2
];
uchar
shentsize
[
2
];
uchar
shnum
[
2
];
uchar
shstrndx
[
2
];
};
struct
ElfHdrBytes64
{
uchar
ident
[
16
];
uchar
type
[
2
];
uchar
machine
[
2
];
uchar
version
[
4
];
uchar
entry
[
8
];
uchar
phoff
[
8
];
uchar
shoff
[
8
];
uchar
flags
[
4
];
uchar
ehsize
[
2
];
uchar
phentsize
[
2
];
uchar
phnum
[
2
];
uchar
shentsize
[
2
];
uchar
shnum
[
2
];
uchar
shstrndx
[
2
];
};
struct
ElfSectBytes
{
uchar
name
[
4
];
uchar
type
[
4
];
uchar
flags
[
4
];
uchar
addr
[
4
];
uchar
off
[
4
];
uchar
size
[
4
];
uchar
link
[
4
];
uchar
info
[
4
];
uchar
align
[
4
];
uchar
entsize
[
4
];
};
struct
ElfSectBytes64
{
uchar
name
[
4
];
uchar
type
[
4
];
uchar
flags
[
8
];
uchar
addr
[
8
];
uchar
off
[
8
];
uchar
size
[
8
];
uchar
link
[
4
];
uchar
info
[
4
];
uchar
align
[
8
];
uchar
entsize
[
8
];
};
struct
ElfSymBytes
{
uchar
name
[
4
];
uchar
value
[
4
];
uchar
size
[
4
];
uchar
info
;
/* top4: bind, bottom4: type */
uchar
other
;
uchar
shndx
[
2
];
};
struct
ElfSymBytes64
{
uchar
name
[
4
];
uchar
info
;
/* top4: bind, bottom4: type */
uchar
other
;
uchar
shndx
[
2
];
uchar
value
[
8
];
uchar
size
[
8
];
};
typedef
struct
ElfSect
ElfSect
;
typedef
struct
ElfObj
ElfObj
;
typedef
struct
ElfSym
ElfSym
;
struct
ElfSect
{
char
*
name
;
uint32
type
;
uint64
flags
;
uint64
addr
;
uint64
off
;
uint64
size
;
uint32
link
;
uint32
info
;
uint64
align
;
uint64
entsize
;
uchar
*
base
;
Sym
*
sym
;
};
struct
ElfObj
{
Biobuf
*
f
;
int64
base
;
// offset in f where ELF begins
int64
len
;
// length of ELF
int
is64
;
char
*
name
;
Endian
*
e
;
ElfSect
*
sect
;
uint
nsect
;
char
*
shstrtab
;
int
nsymtab
;
ElfSect
*
symtab
;
ElfSect
*
symstr
;
uint32
type
;
uint32
machine
;
uint32
version
;
uint64
entry
;
uint64
phoff
;
uint64
shoff
;
uint32
flags
;
uint32
ehsize
;
uint32
phentsize
;
uint32
phnum
;
uint32
shentsize
;
uint32
shnum
;
uint32
shstrndx
;
};
struct
ElfSym
{
char
*
name
;
uint64
value
;
uint64
size
;
uchar
bind
;
uchar
type
;
uchar
other
;
uint16
shndx
;
Sym
*
sym
;
};
uchar
ElfMagic
[
4
]
=
{
0x7F
,
'E'
,
'L'
,
'F'
};
static
ElfSect
*
section
(
ElfObj
*
,
char
*
);
static
int
map
(
ElfObj
*
,
ElfSect
*
);
static
int
readsym
(
ElfObj
*
,
int
i
,
ElfSym
*
);
static
int
reltype
(
char
*
,
int
,
uchar
*
);
void
ldelf
(
Biobuf
*
f
,
char
*
pkg
,
int64
len
,
char
*
pn
)
{
int32
base
;
uint64
add
,
info
;
char
*
name
;
int
i
,
j
,
rela
,
is64
,
n
;
uchar
hdrbuf
[
64
];
uchar
*
p
,
*
dp
;
ElfHdrBytes
*
hdr
;
ElfObj
*
obj
;
ElfSect
*
sect
,
*
rsect
,
*
text
,
*
data
,
*
bss
,
*
rodata
;
ElfSym
sym
;
Endian
*
e
;
Reloc
*
r
,
*
rp
;
Sym
*
s
;
if
(
debug
[
'v'
])
Bprint
(
&
bso
,
"%5.2f ldelf %s
\n
"
,
cputime
(),
pn
);
version
++
;
base
=
Boffset
(
f
);
if
(
Bread
(
f
,
&
hdrbuf
,
sizeof
hdrbuf
)
!=
sizeof
hdrbuf
)
goto
bad
;
hdr
=
(
ElfHdrBytes
*
)
&
hdrbuf
;
if
(
memcmp
(
hdr
->
ident
,
ElfMagic
,
4
)
!=
0
)
goto
bad
;
switch
(
hdr
->
ident
[
5
])
{
case
ElfDataLsb
:
e
=
&
le
;
break
;
case
ElfDataMsb
:
e
=
&
be
;
break
;
default:
goto
bad
;
}
// read header
obj
=
mal
(
sizeof
*
obj
);
obj
->
e
=
e
;
obj
->
f
=
f
;
obj
->
base
=
base
;
obj
->
len
=
len
;
obj
->
name
=
pn
;
is64
=
0
;
if
(
hdr
->
ident
[
4
]
==
ElfClass64
)
{
ElfHdrBytes64
*
hdr
;
is64
=
1
;
hdr
=
(
ElfHdrBytes64
*
)
hdrbuf
;
obj
->
type
=
e
->
e16
(
hdr
->
type
);
obj
->
machine
=
e
->
e16
(
hdr
->
machine
);
obj
->
version
=
e
->
e32
(
hdr
->
version
);
obj
->
phoff
=
e
->
e64
(
hdr
->
phoff
);
obj
->
shoff
=
e
->
e64
(
hdr
->
shoff
);
obj
->
flags
=
e
->
e32
(
hdr
->
flags
);
obj
->
ehsize
=
e
->
e16
(
hdr
->
ehsize
);
obj
->
phentsize
=
e
->
e16
(
hdr
->
phentsize
);
obj
->
phnum
=
e
->
e16
(
hdr
->
phnum
);
obj
->
shentsize
=
e
->
e16
(
hdr
->
shentsize
);
obj
->
shnum
=
e
->
e16
(
hdr
->
shnum
);
obj
->
shstrndx
=
e
->
e16
(
hdr
->
shstrndx
);
}
else
{
obj
->
type
=
e
->
e16
(
hdr
->
type
);
obj
->
machine
=
e
->
e16
(
hdr
->
machine
);
obj
->
version
=
e
->
e32
(
hdr
->
version
);
obj
->
entry
=
e
->
e32
(
hdr
->
entry
);
obj
->
phoff
=
e
->
e32
(
hdr
->
phoff
);
obj
->
shoff
=
e
->
e32
(
hdr
->
shoff
);
obj
->
flags
=
e
->
e32
(
hdr
->
flags
);
obj
->
ehsize
=
e
->
e16
(
hdr
->
ehsize
);
obj
->
phentsize
=
e
->
e16
(
hdr
->
phentsize
);
obj
->
phnum
=
e
->
e16
(
hdr
->
phnum
);
obj
->
shentsize
=
e
->
e16
(
hdr
->
shentsize
);
obj
->
shnum
=
e
->
e16
(
hdr
->
shnum
);
obj
->
shstrndx
=
e
->
e16
(
hdr
->
shstrndx
);
}
obj
->
is64
=
is64
;
if
(
hdr
->
ident
[
6
]
!=
obj
->
version
)
goto
bad
;
if
(
e
->
e16
(
hdr
->
type
)
!=
ElfTypeRelocatable
)
{
diag
(
"%s: elf but not elf relocatable object"
);
return
;
}
switch
(
thechar
)
{
default:
diag
(
"%s: elf %s unimplemented"
,
thestring
);
return
;
case
'5'
:
if
(
e
!=
&
le
||
obj
->
machine
!=
ElfMachArm
||
hdr
->
ident
[
4
]
!=
ElfClass32
)
{
diag
(
"%s: elf object but not arm"
,
pn
);
return
;
}
break
;
case
'6'
:
if
(
e
!=
&
le
||
obj
->
machine
!=
ElfMachAmd64
||
hdr
->
ident
[
4
]
!=
ElfClass64
)
{
diag
(
"%s: elf object but not amd64"
,
pn
);
return
;
}
break
;
case
'8'
:
if
(
e
!=
&
le
||
obj
->
machine
!=
ElfMach386
||
hdr
->
ident
[
4
]
!=
ElfClass32
)
{
diag
(
"%s: elf object but not 386"
,
pn
);
return
;
}
break
;
}
// load section list into memory.
obj
->
sect
=
mal
(
obj
->
shnum
*
sizeof
obj
->
sect
[
0
]);
obj
->
nsect
=
obj
->
shnum
;
for
(
i
=
0
;
i
<
obj
->
nsect
;
i
++
)
{
if
(
Bseek
(
f
,
base
+
obj
->
shoff
+
i
*
obj
->
shentsize
,
0
)
<
0
)
goto
bad
;
sect
=
&
obj
->
sect
[
i
];
if
(
is64
)
{
ElfSectBytes64
b
;
werrstr
(
"short read"
);
if
(
Bread
(
f
,
&
b
,
sizeof
b
)
!=
sizeof
b
)
goto
bad
;
sect
->
name
=
(
char
*
)(
uintptr
)
e
->
e32
(
b
.
name
);
sect
->
type
=
e
->
e32
(
b
.
type
);
sect
->
flags
=
e
->
e64
(
b
.
flags
);
sect
->
addr
=
e
->
e64
(
b
.
addr
);
sect
->
off
=
e
->
e64
(
b
.
off
);
sect
->
size
=
e
->
e64
(
b
.
size
);
sect
->
link
=
e
->
e32
(
b
.
link
);
sect
->
info
=
e
->
e32
(
b
.
info
);
sect
->
align
=
e
->
e64
(
b
.
align
);
sect
->
entsize
=
e
->
e64
(
b
.
entsize
);
}
else
{
ElfSectBytes
b
;
werrstr
(
"short read"
);
if
(
Bread
(
f
,
&
b
,
sizeof
b
)
!=
sizeof
b
)
goto
bad
;
sect
->
name
=
(
char
*
)(
uintptr
)
e
->
e32
(
b
.
name
);
sect
->
type
=
e
->
e32
(
b
.
type
);
sect
->
flags
=
e
->
e32
(
b
.
flags
);
sect
->
addr
=
e
->
e32
(
b
.
addr
);
sect
->
off
=
e
->
e32
(
b
.
off
);
sect
->
size
=
e
->
e32
(
b
.
size
);
sect
->
link
=
e
->
e32
(
b
.
link
);
sect
->
info
=
e
->
e32
(
b
.
info
);
sect
->
align
=
e
->
e32
(
b
.
align
);
sect
->
entsize
=
e
->
e32
(
b
.
entsize
);
}
}
// read section string table and translate names
if
(
obj
->
shstrndx
>=
obj
->
nsect
)
{
werrstr
(
"shstrndx out of range %d >= %d"
,
obj
->
shstrndx
,
obj
->
nsect
);
goto
bad
;
}
sect
=
&
obj
->
sect
[
obj
->
shstrndx
];
if
(
map
(
obj
,
sect
)
<
0
)
goto
bad
;
for
(
i
=
0
;
i
<
obj
->
nsect
;
i
++
)
if
(
obj
->
sect
[
i
].
name
!=
nil
)
obj
->
sect
[
i
].
name
=
(
char
*
)
sect
->
base
+
(
uintptr
)
obj
->
sect
[
i
].
name
;
// load string table for symbols into memory.
obj
->
symtab
=
section
(
obj
,
".symtab"
);
if
(
obj
->
symtab
==
nil
)
{
diag
(
"%s: elf object has no symbol table"
,
pn
);
return
;
}
if
(
obj
->
symtab
->
link
<=
0
||
obj
->
symtab
->
link
>=
obj
->
nsect
)
{
diag
(
"%s: elf object has symbol table with invalid string table link"
,
pn
);
return
;
}
obj
->
symstr
=
&
obj
->
sect
[
obj
->
symtab
->
link
];
if
(
is64
)
obj
->
nsymtab
=
obj
->
symtab
->
size
/
sizeof
(
ElfSymBytes64
);
else
obj
->
nsymtab
=
obj
->
symtab
->
size
/
sizeof
(
ElfSymBytes
);
if
(
map
(
obj
,
obj
->
symtab
)
<
0
)
goto
bad
;
if
(
map
(
obj
,
obj
->
symstr
)
<
0
)
goto
bad
;
// load text and data segments into memory.
// they are not as small as the section lists, but we'll need
// the memory anyway for the symbol images, so we might
// as well use one large chunk.
text
=
section
(
obj
,
".text"
);
if
(
text
&&
map
(
obj
,
text
)
<
0
)
goto
bad
;
data
=
section
(
obj
,
".data"
);
if
(
data
&&
map
(
obj
,
data
)
<
0
)
goto
bad
;
bss
=
section
(
obj
,
".bss"
);
rodata
=
section
(
obj
,
".rodata"
);
if
(
rodata
&&
map
(
obj
,
rodata
)
<
0
)
goto
bad
;
// create symbols for mapped sections
for
(
i
=
0
;
i
<
obj
->
nsect
;
i
++
)
{
sect
=
&
obj
->
sect
[
i
];
if
(
sect
->
type
!=
ElfSectProgbits
||
!
(
sect
->
flags
&
ElfSectFlagAlloc
))
continue
;
if
(
map
(
obj
,
sect
)
<
0
)
goto
bad
;
name
=
smprint
(
"%s(%s)"
,
pn
,
sect
->
name
);
s
=
lookup
(
name
,
version
);
free
(
name
);
switch
(
sect
->
flags
&
(
ElfSectFlagAlloc
|
ElfSectFlagWrite
|
ElfSectFlagExec
))
{
default:
werrstr
(
"unexpected flags for ELF section %s"
,
sect
->
name
);
goto
bad
;
case
ElfSectFlagAlloc
:
s
->
type
=
SRODATA
;
break
;
case
ElfSectFlagAlloc
+
ElfSectFlagWrite
:
s
->
type
=
SDATA
;
break
;
case
ElfSectFlagAlloc
+
ElfSectFlagExec
:
s
->
type
=
STEXT
;
break
;
}
s
->
p
=
sect
->
base
;
s
->
np
=
sect
->
size
;
s
->
size
=
sect
->
size
;
if
(
s
->
type
==
STEXT
)
{
if
(
etextp
)
etextp
->
next
=
s
;
else
textp
=
s
;
etextp
=
s
;
}
sect
->
sym
=
s
;
}
// load relocations
for
(
i
=
0
;
i
<
obj
->
nsect
;
i
++
)
{
rsect
=
&
obj
->
sect
[
i
];
if
(
rsect
->
type
!=
ElfSectRela
&&
rsect
->
type
!=
ElfSectRel
)
continue
;
if
(
rsect
->
info
>=
obj
->
nsect
||
obj
->
sect
[
rsect
->
info
].
base
==
nil
)
continue
;
sect
=
&
obj
->
sect
[
rsect
->
info
];
if
(
map
(
obj
,
rsect
)
<
0
)
goto
bad
;
rela
=
rsect
->
type
==
ElfSectRela
;
n
=
rsect
->
size
/
(
4
+
4
*
is64
)
/
(
2
+
rela
);
r
=
mal
(
n
*
sizeof
r
[
0
]);
p
=
rsect
->
base
;
dp
=
sect
->
base
;
for
(
j
=
0
;
j
<
n
;
j
++
)
{
add
=
0
;
rp
=
&
r
[
j
];
if
(
is64
)
{
// 64-bit rel/rela
rp
->
off
=
e
->
e64
(
p
);
p
+=
8
;
info
=
e
->
e64
(
p
);
p
+=
8
;
if
(
rela
)
{
add
=
e
->
e64
(
p
);
p
+=
8
;
}
}
else
{
// 32-bit rel/rela
rp
->
off
=
e
->
e32
(
p
);
p
+=
4
;
info
=
e
->
e32
(
p
);
info
=
info
>>
8
<<
32
|
(
info
&
0xff
);
// convert to 64-bit info
p
+=
4
;
if
(
rela
)
{
add
=
e
->
e32
(
p
);
p
+=
4
;
}
}
if
(
readsym
(
obj
,
info
>>
32
,
&
sym
)
<
0
)
goto
bad
;
if
(
sym
.
sym
==
nil
)
{
werrstr
(
"reloc of invalid sym %s shndx=%d type=%d"
,
sym
.
name
,
sym
.
shndx
,
sym
.
type
);
goto
bad
;
}
rp
->
sym
=
sym
.
sym
;
rp
->
type
=
reltype
(
pn
,
(
uint32
)
info
,
&
rp
->
siz
);
if
(
rela
)
rp
->
add
=
add
;
else
{
// load addend from image
if
(
rp
->
siz
==
4
)
rp
->
add
=
e
->
e32
(
sect
->
base
+
rp
->
off
);
else
if
(
rp
->
siz
==
8
)
rp
->
add
=
e
->
e64
(
sect
->
base
+
rp
->
off
);
else
diag
(
"invalid rela size %d"
,
rp
->
siz
);
}
}
qsort
(
r
,
n
,
sizeof
r
[
0
],
rbyoff
);
// just in case
s
=
sect
->
sym
;
s
->
r
=
r
;
s
->
nr
=
n
;
}
// enter sub-symbols into symbol table.
// symbol 0 is the null symbol.
for
(
i
=
1
;
i
<
obj
->
nsymtab
;
i
++
)
{
if
(
readsym
(
obj
,
i
,
&
sym
)
<
0
)
goto
bad
;
if
(
sym
.
type
!=
ElfSymTypeFunc
&&
sym
.
type
!=
ElfSymTypeObject
&&
sym
.
type
!=
ElfSymTypeNone
)
continue
;
if
(
sym
.
shndx
==
ElfSymShnCommon
)
{
s
=
sym
.
sym
;
if
(
s
->
size
<
sym
.
size
)
s
->
size
=
sym
.
size
;
if
(
s
->
type
==
0
||
s
->
type
==
SXREF
)
s
->
type
=
SBSS
;
continue
;
}
if
(
sym
.
shndx
>=
obj
->
nsect
||
sym
.
shndx
==
0
)
continue
;
sect
=
obj
->
sect
+
sym
.
shndx
;
if
(
sect
->
sym
==
nil
)
{
diag
(
"%s: sym#%d: ignoring %s in section %d (type %d)"
,
pn
,
i
,
sym
.
name
,
sym
.
shndx
,
sym
.
type
);
continue
;
}
s
=
sym
.
sym
;
s
->
sub
=
sect
->
sym
->
sub
;
sect
->
sym
->
sub
=
s
;
s
->
type
=
sect
->
sym
->
type
|
SSUB
;
s
->
dynimplib
=
nil
;
// satisfy dynimport
s
->
dynimpname
=
nil
;
// satisfy dynimport
s
->
value
=
sym
.
value
;
s
->
size
=
sym
.
size
;
s
->
outer
=
sect
->
sym
;
if
(
sect
->
sym
->
type
==
STEXT
)
{
Prog
*
p
;
if
(
s
->
text
!=
P
)
diag
(
"%s: duplicate definition of %s"
,
pn
,
s
->
name
);
// build a TEXT instruction with a unique pc
// just to make the rest of the linker happy.
// TODO: this is too 6l-specific ?
p
=
prg
();
p
->
as
=
ATEXT
;
p
->
from
.
type
=
D_EXTERN
;
p
->
from
.
sym
=
s
;
p
->
from
.
scale
=
7
;
p
->
to
.
type
=
D_CONST
;
p
->
link
=
nil
;
p
->
pc
=
pc
++
;
s
->
text
=
p
;
etextp
->
next
=
s
;
etextp
=
s
;
}
}
return
;
bad:
diag
(
"%s: malformed elf file: %r"
,
pn
);
}
static
ElfSect
*
section
(
ElfObj
*
obj
,
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
obj
->
nsect
;
i
++
)
if
(
obj
->
sect
[
i
].
name
&&
name
&&
strcmp
(
obj
->
sect
[
i
].
name
,
name
)
==
0
)
return
&
obj
->
sect
[
i
];
return
nil
;
}
static
int
map
(
ElfObj
*
obj
,
ElfSect
*
sect
)
{
if
(
sect
->
base
!=
nil
)
return
0
;
if
(
sect
->
off
+
sect
->
size
>
obj
->
len
)
{
werrstr
(
"elf section past end of file"
);
return
-
1
;
}
sect
->
base
=
mal
(
sect
->
size
);
werrstr
(
"short read"
);
if
(
Bseek
(
obj
->
f
,
obj
->
base
+
sect
->
off
,
0
)
<
0
||
Bread
(
obj
->
f
,
sect
->
base
,
sect
->
size
)
!=
sect
->
size
)
return
-
1
;
return
0
;
}
static
int
readsym
(
ElfObj
*
obj
,
int
i
,
ElfSym
*
sym
)
{
Sym
*
s
;
if
(
i
>=
obj
->
nsymtab
||
i
<
0
)
{
werrstr
(
"invalid elf symbol index"
);
return
-
1
;
}
if
(
obj
->
is64
)
{
ElfSymBytes64
*
b
;
b
=
(
ElfSymBytes64
*
)(
obj
->
symtab
->
base
+
i
*
sizeof
*
b
);
sym
->
name
=
(
char
*
)
obj
->
symstr
->
base
+
obj
->
e
->
e32
(
b
->
name
);
sym
->
value
=
obj
->
e
->
e64
(
b
->
value
);
sym
->
size
=
obj
->
e
->
e64
(
b
->
size
);
sym
->
shndx
=
obj
->
e
->
e16
(
b
->
shndx
);
sym
->
bind
=
b
->
info
>>
4
;
sym
->
type
=
b
->
info
&
0xf
;
sym
->
other
=
b
->
other
;
}
else
{
ElfSymBytes
*
b
;
b
=
(
ElfSymBytes
*
)(
obj
->
symtab
->
base
+
i
*
sizeof
*
b
);
sym
->
name
=
(
char
*
)
obj
->
symstr
->
base
+
obj
->
e
->
e32
(
b
->
name
);
sym
->
value
=
obj
->
e
->
e32
(
b
->
value
);
sym
->
size
=
obj
->
e
->
e32
(
b
->
size
);
sym
->
shndx
=
obj
->
e
->
e16
(
b
->
shndx
);
sym
->
bind
=
b
->
info
>>
4
;
sym
->
type
=
b
->
info
&
0xf
;
sym
->
other
=
b
->
other
;
}
s
=
nil
;
if
(
strcmp
(
sym
->
name
,
"_GLOBAL_OFFSET_TABLE_"
)
==
0
)
sym
->
name
=
".got"
;
if
(
strcmp
(
sym
->
name
,
"__stack_chk_fail_local"
)
==
0
)
sym
->
other
=
0
;
// rewrite hidden -> default visibility
switch
(
sym
->
type
)
{
case
ElfSymTypeSection
:
s
=
obj
->
sect
[
sym
->
shndx
].
sym
;
break
;
case
ElfSymTypeObject
:
case
ElfSymTypeFunc
:
case
ElfSymTypeNone
:
switch
(
sym
->
bind
)
{
case
ElfSymBindGlobal
:
if
(
sym
->
other
!=
2
)
{
s
=
lookup
(
sym
->
name
,
0
);
break
;
}
// fall through
case
ElfSymBindLocal
:
s
=
lookup
(
sym
->
name
,
version
);
break
;
default:
werrstr
(
"%s: invalid symbol binding %d"
,
sym
->
name
,
sym
->
bind
);
return
-
1
;
}
break
;
}
if
(
s
!=
nil
&&
s
->
type
==
0
&&
sym
->
type
!=
ElfSymTypeSection
)
s
->
type
=
SXREF
;
sym
->
sym
=
s
;
return
0
;
}
int
rbyoff
(
const
void
*
va
,
const
void
*
vb
)
{
Reloc
*
a
,
*
b
;
a
=
(
Reloc
*
)
va
;
b
=
(
Reloc
*
)
vb
;
if
(
a
->
off
<
b
->
off
)
return
-
1
;
if
(
a
->
off
>
b
->
off
)
return
+
1
;
return
0
;
}
#define R(x, y) ((x)|((y)<<24))
static
int
reltype
(
char
*
pn
,
int
elftype
,
uchar
*
siz
)
{
switch
(
R
(
thechar
,
elftype
))
{
default:
diag
(
"%s: unknown relocation type %d; compiled without -fpic?"
,
pn
,
elftype
);
case
R
(
'6'
,
R_X86_64_PC32
):
case
R
(
'6'
,
R_X86_64_PLT32
):
case
R
(
'6'
,
R_X86_64_GOTPCREL
):
case
R
(
'8'
,
R_386_32
):
case
R
(
'8'
,
R_386_PC32
):
case
R
(
'8'
,
R_386_GOT32
):
case
R
(
'8'
,
R_386_PLT32
):
case
R
(
'8'
,
R_386_GOTOFF
):
case
R
(
'8'
,
R_386_GOTPC
):
*
siz
=
4
;
break
;
case
R
(
'6'
,
R_X86_64_64
):
*
siz
=
8
;
break
;
}
return
256
+
elftype
;
}
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