Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
PoroCYon
smol
Commits
7e384a44
Commit
7e384a44
authored
May 03, 2020
by
PoroCYon
Committed by
PoroCYon
Jul 11, 2020
Browse files
fix smoldd
parent
5c38b05c
Changes
5
Show whitespace changes
Inline
Side-by-side
smoldd.py
deleted
100755 → 0
View file @
5c38b05c
#!/usr/bin/env python3
import
argparse
import
glob
import
os.path
import
shutil
import
subprocess
import
struct
import
sys
from
smolshared
import
*
def
readbyte
(
blob
,
off
):
return
struct
.
unpack
(
'<B'
,
blob
[
off
:
off
+
1
])[
0
],
(
off
+
1
)
def
readint
(
blob
,
off
):
return
struct
.
unpack
(
'<I'
,
blob
[
off
:
off
+
4
])[
0
],
(
off
+
4
)
def
readlong
(
blob
,
off
):
return
struct
.
unpack
(
'<Q'
,
blob
[
off
:
off
+
8
])[
0
],
(
off
+
8
)
def
readstr
(
blob
,
off
):
text
=
bytearray
()
while
True
:
char
,
off
=
readbyte
(
blob
,
off
)
if
char
==
0
:
break
text
.
append
(
char
)
return
text
.
decode
(
'utf-8'
),
off
def
get_def_libpaths
(
cc_bin
,
is32bit
):
if
is32bit
:
return
[
'/usr/lib32/'
,
'/lib32/'
]
out
=
subprocess
.
check_output
([
cc_bin
,
'-print-search-dirs'
],
stderr
=
subprocess
.
DEVNULL
)
stuff
=
dict
({})
for
l
in
out
.
decode
(
'utf-8'
).
splitlines
():
blah
=
l
.
split
(
': '
)
stuff
[
blah
[
0
]]
=
blah
[
1
].
lstrip
(
'='
).
split
(
':'
)
return
stuff
[
"libraries"
]
def
find_libs
(
bits
,
deflibs
,
libname
):
dirs
=
os
.
environ
[
'LD_LIBRARY_PATH'
].
split
(
':'
)
+
deflibs
for
d
in
dirs
:
for
f
in
glob
.
glob
(
glob
.
escape
(
d
+
libname
)
+
'*'
):
yield
f
def
build_hashtab
(
scanelf_bin
,
lib
):
out
=
subprocess
.
check_output
([
scanelf_bin
,
'-B'
,
'-F'
,
'%s'
,
'-s'
,
'%pd%*'
,
lib
],
stderr
=
subprocess
.
DEVNULL
)
blah
=
set
(
out
.
decode
(
'utf-8'
).
split
(
'
\n
'
))
ret
=
dict
({})
for
x
in
blah
:
y
=
x
.
split
()
if
len
(
y
)
!=
7
:
continue
ret
[
hash_djb2
(
y
[
6
])]
=
y
[
6
]
return
ret
def
main
():
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'input'
,
type
=
argparse
.
FileType
(
'rb'
),
default
=
sys
.
stdin
.
buffer
,
help
=
"input file"
)
parser
.
add_argument
(
'--cc'
,
default
=
shutil
.
which
(
'cc'
),
help
=
"C compiler binary"
)
parser
.
add_argument
(
'--scanelf'
,
default
=
shutil
.
which
(
'scanelf'
),
help
=
"scanelf binary"
)
args
=
parser
.
parse_args
()
blob
=
args
.
input
.
read
()
machnum
=
struct
.
unpack
(
'<H'
,
blob
[
18
:
18
+
2
])[
0
]
is32bit
=
machnum
==
archmagic
[
'i386'
]
deflibs
=
get_def_libpaths
(
args
.
cc
,
is32bit
)
phoff
,
phsz
,
phnum
=
0
,
0
,
0
if
is32bit
:
phoff
=
struct
.
unpack
(
'<I'
,
blob
[
28
:
28
+
4
])[
0
]
phsz
=
struct
.
unpack
(
'<H'
,
blob
[
42
:
42
+
2
])[
0
]
phnum
=
struct
.
unpack
(
'<H'
,
blob
[
44
:
52
+
2
])[
0
]
elif
machnum
==
archmagic
[
'x86_64'
]:
phoff
=
struct
.
unpack
(
'<Q'
,
blob
[
32
:
32
+
8
])[
0
]
phsz
=
struct
.
unpack
(
'<H'
,
blob
[
54
:
54
+
2
])[
0
]
phnum
=
struct
.
unpack
(
'<H'
,
blob
[
56
:
56
+
2
])[
0
]
else
:
eprintf
(
"Unknown architecture "
+
str
(
machnum
))
sys
.
exit
(
1
)
for
i
in
range
(
phnum
):
off
=
phoff
+
i
*
phsz
#print(hex(off))
ptyp
,
poff
,
pva
,
ppa
,
pfsz
,
pmsz
,
pfl
,
pal
=
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
if
is32bit
:
ptyp
,
poff
,
pva
,
ppa
,
pfsz
,
pmsz
,
pfl
,
pal
=
\
struct
.
unpack
(
'<ILLLIIII'
,
blob
[
off
:
off
+
phsz
])
else
:
ptyp
,
pfl
,
poff
,
pva
,
ppa
,
pfsz
,
pmsz
,
pal
=
\
struct
.
unpack
(
'<IIQQQQQQ'
,
blob
[
off
:
off
+
phsz
])
if
ptyp
!=
2
:
# PT_DYNAMIC
continue
#print(hex(poff))
# right after the dynamic section, the smol 'symtab'/'hashtab' is found
#
# note that on i386, every lib name is followed by an E9 byte
# if the next libname/first byte of the hash is null, the table has
# come to an end.
if
is32bit
:
j
=
poff
strtaboff
=
0
while
j
<
poff
+
pfsz
:
tag
,
j
=
readint
(
blob
,
j
)
ptr
,
j
=
readint
(
blob
,
j
)
if
tag
==
5
:
# DT_STRTAB
strtaboff
=
ptr
elif
tag
==
1
:
# DT_NEEDED
bakoff
=
j
smoltaboff
=
strtaboff
+
ptr
-
(
pva
-
poff
)
j
=
smoltaboff
libname
,
j
=
readstr
(
blob
,
j
)
if
len
(
libname
)
==
0
:
break
sys
.
stdout
.
write
(
"* "
+
libname
)
libs
=
list
(
find_libs
(
32
,
deflibs
,
libname
))
print
(
" -> NOT FOUND"
if
len
(
libs
)
==
0
else
(
" -> "
+
libs
[
0
]))
ht
=
dict
({})
if
len
(
libs
)
==
0
else
build_hashtab
(
args
.
scanelf
,
libs
[
0
])
while
True
:
hashv
,
j
=
readint
(
blob
,
j
)
if
(
hashv
&
0xFF
)
==
0
:
break
sys
.
stdout
.
write
(
" * "
+
hex
(
hashv
))
print
(
" -> NOT FOUND"
if
hashv
not
in
ht
else
(
" -> "
+
ht
[
hashv
]))
j
=
bakoff
break
else
:
# 64-bit
eprintf
(
"Currently unsuppored, sorry."
)
sys
.
exit
(
1
)
if
__name__
==
'__main__'
:
main
()
src/hackyelf.py
0 → 100644
View file @
7e384a44
# stolen from the contrib folder in https://github.com/blackle/LZMA-Vizualizer
# (i.e. I'm stealing it from myself)
# custom elf parser because a standard one wouldn't be trustable because the
# ELFs we're parsing will be a bit wonky anyway
from
struct
import
unpack
from
typing
import
*
ELFCLASS32
=
1
ELFCLASS64
=
2
EM_386
=
3
EM_X86_64
=
62
PT_NULL
=
0
PT_LOAD
=
1
PT_DYNAMIC
=
2
PT_INTERP
=
3
DT_NULL
=
0
DT_NEEDED
=
1
DT_STRTAB
=
5
DT_SYMTAB
=
6
class
Phdr
(
NamedTuple
):
ptype
:
int
off
:
int
vaddr
:
int
paddr
:
int
filesz
:
int
memsz
:
int
flags
:
int
align
:
int
class
Dyn
(
NamedTuple
):
tag
:
int
val
:
int
class
ELF
(
NamedTuple
):
data
:
bytes
ident
:
bytes
eclass
:
int
mach
:
int
entry
:
int
phdrs
:
Sequence
[
Phdr
]
dyn
:
Sequence
[
Dyn
]
is32bit
:
bool
# yeah, there's some code duplication here
# idgaf
def
parse_phdr32
(
data
:
bytes
,
phoff
:
int
,
phentsz
:
int
,
phnum
:
int
)
->
Sequence
[
Phdr
]:
ps
=
[]
for
off
in
range
(
phoff
,
phoff
+
phentsz
*
phnum
,
phentsz
):
ptype
,
off
,
vaddr
,
paddr
,
filesz
,
memsz
,
flags
,
align
=
\
unpack
(
'<IIIIIIII'
,
data
[
off
:
off
+
8
*
4
])
p
=
Phdr
(
ptype
,
off
,
vaddr
,
paddr
,
filesz
,
memsz
,
flags
,
align
)
ps
.
append
(
p
)
return
ps
def
parse_dyn32
(
data
:
bytes
,
dynp
:
Phdr
)
->
Dyn
:
ds
=
[]
off
=
dynp
.
off
while
True
:
tag
,
val
=
unpack
(
'<II'
,
data
[
off
:
off
+
2
*
4
])
ds
.
append
(
Dyn
(
tag
,
val
))
if
tag
==
DT_NULL
:
break
off
=
off
+
2
*
4
return
ds
def
parse_32
(
data
:
bytes
)
->
ELF
:
ident
=
data
[:
16
]
eclass
=
data
[
4
]
mach
=
unpack
(
'<H'
,
data
[
18
:
18
+
2
])[
0
]
entry
=
unpack
(
'<I'
,
data
[
24
:
24
+
4
])[
0
]
phoff
=
unpack
(
'<I'
,
data
[
28
:
28
+
4
])[
0
]
phentsz
=
unpack
(
'<H'
,
data
[
42
:
42
+
2
])[
0
]
phnum
=
unpack
(
'<H'
,
data
[
44
:
44
+
2
])[
0
]
phdrs
=
parse_phdr32
(
data
,
phoff
,
phentsz
,
phnum
)
dyn
=
None
for
p
in
phdrs
:
if
p
.
ptype
==
PT_DYNAMIC
:
dyn
=
parse_dyn32
(
data
,
p
)
break
return
ELF
(
data
,
ident
,
eclass
,
mach
,
entry
,
phdrs
,
dyn
,
True
)
def
parse_phdr64
(
data
:
bytes
,
phoff
:
int
,
phentsz
:
int
,
phnum
:
int
)
->
Sequence
[
Phdr
]:
ps
=
[]
for
off
in
range
(
phoff
,
phoff
+
phentsz
*
phnum
,
phentsz
):
# TODO
ptype
,
flags
,
off
,
vaddr
,
paddr
,
filesz
,
memsz
,
align
=
\
unpack
(
'<IIQQQQQQ'
,
data
[
off
:
off
+
2
*
4
+
6
*
8
])
p
=
Phdr
(
ptype
,
off
,
vaddr
,
paddr
,
filesz
,
memsz
,
flags
,
align
)
ps
.
append
(
p
)
return
ps
def
parse_dyn64
(
data
:
bytes
,
dynp
:
Phdr
)
->
Dyn
:
ds
=
[]
off
=
dynp
.
off
while
True
:
tag
,
val
=
unpack
(
'<QQ'
,
data
[
off
:
off
+
2
*
8
])
ds
.
append
(
Dyn
(
tag
,
val
))
if
tag
==
DT_NULL
:
break
off
=
off
+
2
*
8
return
ds
def
parse_64
(
data
:
bytes
)
->
ELF
:
ident
=
data
[:
16
]
eclass
=
data
[
4
]
mach
=
unpack
(
'<H'
,
data
[
18
:
18
+
2
])[
0
]
entry
=
unpack
(
'<Q'
,
data
[
24
:
24
+
8
])[
0
]
phoff
=
unpack
(
'<Q'
,
data
[
32
:
32
+
8
])[
0
]
phentsz
=
unpack
(
'<H'
,
data
[
54
:
54
+
2
])[
0
]
phnum
=
unpack
(
'<H'
,
data
[
56
:
56
+
2
])[
0
]
phdrs
=
parse_phdr64
(
data
,
phoff
,
phentsz
,
phnum
)
dyn
=
None
for
p
in
phdrs
:
if
p
.
ptype
==
PT_DYNAMIC
:
dyn
=
parse_dyn64
(
data
,
p
)
break
return
ELF
(
data
,
ident
,
eclass
,
mach
,
entry
,
phdrs
,
dyn
,
False
)
def
parse
(
data
:
bytes
)
->
ELF
:
assert
data
[:
4
]
==
b
'
\x7F
ELF'
,
"Not a valid ELF file"
# good enough
ecls
=
data
[
4
]
if
ecls
==
ELFCLASS32
:
return
parse_32
(
data
)
elif
ecls
==
ELFCLASS64
:
return
parse_64
(
data
)
else
:
emch
=
unpack
(
'<H'
,
data
[
18
:
18
+
2
])[
0
]
if
emch
==
EM_386
:
return
parse_32
(
data
)
elif
emch
==
EM_X86_64
:
return
parse_64
(
data
)
assert
False
,
"bad E_CLASS %d"
%
ecls
src/linkmap.py
0 → 100644
View file @
7e384a44
# stolen from the contrib folder in https://github.com/blackle/LZMA-Vizualizer
# (i.e. I'm stealing it from myself)
import
re
from
typing
import
*
class
CommonSym
(
NamedTuple
):
name
:
str
size
:
int
file
:
str
class
Discard
(
NamedTuple
):
name
:
str
size
:
int
file
:
str
class
MemCfg
(
NamedTuple
):
name
:
str
org
:
int
size
:
int
class
MMap
(
NamedTuple
):
sect
:
str
org
:
int
#size: int
sym
:
str
file
:
str
class
XRef
(
NamedTuple
):
name
:
str
deff
:
str
reff
:
Sequence
[
str
]
class
LinkMap
(
NamedTuple
):
common
:
Sequence
[
CommonSym
]
discard
:
Sequence
[
Discard
]
memcfg
:
Sequence
[
MemCfg
]
mmap
:
Sequence
[
MMap
]
xref
:
Sequence
[
XRef
]
def
parse_common
(
ls
:
Sequence
[
str
])
->
Sequence
[
CommonSym
]:
return
[]
# TODO
def
parse_discard
(
ls
:
Sequence
[
str
])
->
Sequence
[
Discard
]:
return
[]
# TODO
def
parse_memcfg
(
ls
:
Sequence
[
str
])
->
Sequence
[
MemCfg
]:
return
[]
# TODO
def
parse_xref
(
ls
:
Sequence
[
str
])
->
Sequence
[
XRef
]:
return
[]
# TODO
def
parse_mmap
(
ls
:
Sequence
[
str
])
->
Sequence
[
MMap
]:
rrr
=
[]
bigsect
=
None
section
=
None
curfile
=
None
#size = -1
for
l
in
ls
:
def
matcher
(
mobj
):
return
mobj
.
group
(
0
).
replace
(
' '
,
'_'
)
l
=
re
.
sub
(
r
"\*\(.*\)"
,
matcher
,
l
)
#print(repr(l))
s
=
l
.
strip
();
w
=
s
.
split
()
if
s
.
startswith
(
'LOAD '
)
or
s
.
startswith
(
'OUTPUT('
):
continue
#break
if
l
[
0
]
!=
' '
:
bigsect
=
w
[
0
]
del
w
[
0
]
elif
l
[
1
]
!=
' '
:
section
=
w
[
0
]
del
w
[
0
]
if
len
(
w
)
==
0
or
w
[
0
]
==
"[!provide]"
:
continue
# addr placed on next line for prettyprinting reasons
#print(repr(l), w[0])
assert
w
[
0
].
startswith
(
"0x"
),
"welp, bad symbol addr"
addr
=
int
(
w
[
0
],
16
)
size
=
-
1
symn
=
""
if
w
[
1
].
startswith
(
"0x"
):
# filename will prolly follow
size
=
int
(
w
[
1
],
16
)
curfile
=
w
[
2
]
if
len
(
w
)
>
2
else
""
else
:
symn
=
w
[
1
]
if
len
(
symn
)
>
0
:
rrr
.
append
(
MMap
(
section
,
addr
,
symn
,
curfile
))
return
rrr
def
parse
(
s
:
str
)
->
LinkMap
:
COMMON
=
0
DISCARD
=
1
MEMCFG
=
2
MMAP
=
3
XREF
=
4
curpt
=
-
1
commonl
,
discardl
,
memcfgl
,
mmapl
,
xrefl
=
[],
[],
[],
[],
[]
for
l
in
s
.
split
(
'
\n
'
):
if
len
(
l
.
strip
())
==
0
:
continue
ls
=
l
.
strip
()
if
ls
==
"Allocating common symbols"
:
curpt
=
COMMON
elif
ls
==
"Discarded input sections"
:
curpt
=
DISCARD
elif
ls
==
"Memory Configuration"
:
curpt
=
MEMCFG
elif
ls
==
"Linker script and memory map"
:
curpt
=
MMAP
elif
ls
==
'Cross Reference Table'
:
curpt
=
XREF
elif
curpt
==
COMMON
:
commonl
.
append
(
l
)
elif
curpt
==
DISCARD
:
discardl
.
append
(
l
)
elif
curpt
==
MEMCFG
:
memcfgl
.
append
(
l
)
elif
curpt
==
MMAP
:
mmapl
.
append
(
l
)
elif
curpt
==
XREF
:
xrefl
.
append
(
l
)
else
:
assert
False
,
"bad line %s"
%
ls
return
LinkMap
(
parse_common
(
commonl
),
parse_discard
(
discardl
),
\
parse_memcfg
(
memcfgl
),
parse_mmap
(
mmapl
),
parse_xref
(
xrefl
))
src/smoldd.py
0 → 100755
View file @
7e384a44
#!/usr/bin/env python3
import
os.path
,
struct
,
sys
import
argparse
,
glob
,
shutil
,
subprocess
import
hackyelf
,
linkmap
from
smolshared
import
*
from
smolparse
import
*
def
readbyte
(
blob
,
off
):
return
struct
.
unpack
(
'<B'
,
blob
[
off
:
off
+
1
])[
0
],
(
off
+
1
)
def
readint
(
blob
,
off
):
return
struct
.
unpack
(
'<I'
,
blob
[
off
:
off
+
4
])[
0
],
(
off
+
4
)
def
readlong
(
blob
,
off
):
return
struct
.
unpack
(
'<Q'
,
blob
[
off
:
off
+
8
])[
0
],
(
off
+
8
)
def
readstr
(
blob
,
off
):
text
=
bytearray
()
while
True
:
char
,
off
=
readbyte
(
blob
,
off
)
if
char
==
0
:
break
text
.
append
(
char
)
return
text
.
decode
(
'utf-8'
),
off
def
get_def_libpaths
(
cc_bin
,
is32bit
):
# FIXME: HACK
if
is32bit
:
return
[
'/usr/lib32/'
,
'/lib32/'
]
return
get_cc_paths
(
cc_bin
)[
'libraries'
]
def
find_libs
(
deflibs
,
libname
):
dirs
=
os
.
environ
[
'LD_LIBRARY_PATH'
].
split
(
':'
)
+
deflibs
for
d
in
dirs
:
for
f
in
glob
.
glob
(
glob
.
escape
(
d
+
'/'
+
libname
)
+
'*'
):
yield
f
def
build_hashtab
(
scanelf_bin
,
lib
):
out
=
subprocess
.
check_output
([
scanelf_bin
,
'-B'
,
'-F'
,
'%s'
,
'-s'
,
'%pd%*'
,
lib
],
stderr
=
subprocess
.
DEVNULL
)
blah
=
set
(
out
.
decode
(
'utf-8'
).
split
(
'
\n
'
))
ret
=
dict
({})
for
x
in
blah
:
y
=
x
.
split
()
if
len
(
y
)
!=
7
:
continue
ret
[
hash_djb2
(
y
[
6
])]
=
y
[
6
]
return
ret
def
addr2off
(
elf
,
addr
):
for
x
in
elf
.
phdrs
:
if
x
.
ptype
!=
hackyelf
.
PT_LOAD
:
continue
if
addr
>=
x
.
vaddr
and
addr
<
x
.
vaddr
+
x
.
memsz
:
aoff
=
addr
-
x
.
vaddr
assert
aoff
<
x
.
filesz
,
".bss address!"
return
aoff
+
x
.
off
assert
False
,
"Address %08x not in the static address range!"
%
addr
def
get_needed_libs
(
elf
,
blob
):
assert
elf
.
dyn
is
not
None
,
"No DYNAMIC table present in the ELF file!"
strtabs
=
[
x
.
val
for
x
in
elf
.
dyn
if
x
.
tag
==
hackyelf
.
DT_STRTAB
]
assert
len
(
strtabs
)
==
1
,
"Only one DT_STRTAB may be present in an ELF file."
strtab
=
strtabs
[
0
]
return
[
readstr
(
blob
,
addr2off
(
elf
,
strtab
+
x
.
val
))[
0
]
for
x
in
elf
.
dyn
if
x
.
tag
==
hackyelf
.
DT_NEEDED
]
def
get_hashtbl
(
elf
,
blob
,
args
):
htaddr
=
None
if
args
.
map
is
not
None
:
lmap
=
linkmap
.
parse
(
args
.
map
.
read
())
tabs
=
[
x
for
x
in
lmap
.
mmap
if
x
.
sym
==
'_symbols'
]
assert
len
(
tabs
)
==
1
,
"One '_symbols' symbol must be present."
htaddr
=
tabs
[
0
].
org
elif
elf
.
is32bit
:
txtoff
=
addr2off
(
elf
,
elf
.
entry
)
# scan for 'push IMM32'
while
blob
[
txtoff
]
!=
0x68
:
txtoff
=
txtoff
+
1
assert
txtoff
<
len
(
blob
),
"wtf??? (can't find a push IMM32 instruction which pushes the hashtable address)"
txtoff
=
txtoff
+
1
htaddr
=
struct
.
unpack
(
'<I'
,
blob
[
txtoff
:
txtoff
+
4
])[
0
]
else
:
# 64-bit
txtoff
=
addr2off
(
elf
,
elf
.
entry
)
# scan for 'push IMM32'
# but the first one we'll encounter pushes the entrypoint addr!
while
blob
[
txtoff
]
!=
0x68
:
txtoff
=
txtoff
+
1
assert
txtoff
<
len
(
blob
),
"wtf??? (can't find a push IMM32 instruction which pushes the entrypoint address)"
txtoff
=
txtoff
+
1
# now we can look for the interesting address
while
blob
[
txtoff
]
!=
0x68
:
txtoff
=
txtoff
+
1
assert
txtoff
<
len
(
blob
),
"wtf??? (can't find a push IMM32 instruction which pushes the hashtable address)"
txtoff
=
txtoff
+
1
htaddr
=
struct
.
unpack
(
'<I'
,
blob
[
txtoff
:
txtoff
+
4
])[
0
]
assert
htaddr
is
not
None
,
"wtf? (no hashtable address)"
print
(
"Hash table address: 0x%08x"
%
htaddr
)
htoff
=
addr2off
(
elf
,
htaddr
)
tbl
=
[]
while
True
:
if
len
(
blob
)
-
htoff
<
4
:
if
struct
.
unpack
(
'<B'
,
blob
[
htoff
:
htoff
+
1
])[
0
]
==
0
:
break
val
=
struct
.
unpack
(
'<I'
,
blob
[
htoff
:
htoff
+
4
])[
0
]
if
(
val
&
0xFF
)
==
0
:
break
tbl
.
append
(
val
)
htoff
=
htoff
+
(
4
if
elf
.
is32bit
else
8
)
return
tbl
def
main
():
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'input'
,
type
=
argparse
.
FileType
(
'rb'
),
default
=
sys
.
stdin
.
buffer
,
help
=
"input file"
)
parser
.
add_argument
(
'--cc'
,
default
=
shutil
.
which
(
'cc'
),
help
=
"C compiler binary"
)
parser
.
add_argument
(
'--scanelf'
,
default
=
shutil
.
which
(
'scanelf'
),
help
=
"scanelf binary"
)
parser
.
add_argument
(
'--map'
,
type
=
argparse
.
FileType
(
'r'
),
help
=
\
"Get the address of the symbol hash table from the "
+
\
"linker map output instead of attempting to parse the"
+
\
" binary."
)
args
=
parser
.
parse_args
()
blob
=
args
.
input
.
read
()
elf
=
hackyelf
.
parse
(
blob
)
deflibs
=
get_def_libpaths
(
args
.
cc
,
elf
.
is32bit
)
needed
=
get_needed_libs
(
elf
,
blob
)
neededpaths
=
dict
((
l
,
list
(
find_libs
(
deflibs
,
l
))[
0
])
for
l
in
needed
)
htbl
=
get_hashtbl
(
elf
,
blob
,
args
)
libhashes
=
dict
((
l
,
build_hashtab
(
args
.
scanelf
,
neededpaths
[
l
]))
for
l
in
needed
)
hashresolves
=
dict
({})
noresolves
=
[]
# TODO: group by libs
for
x
in
htbl
:
done
=
False
for
l
in
libhashes
.
keys
():
v
=
libhashes
[
l
]
if
x
in
v
:
if
l
not
in
hashresolves
:
hashresolves
[
l
]
=
dict
({})
hashresolves
[
l
][
x
]
=
v
[
x
]
done
=
True
break
if
not
done
:
noresolves
.
append
(
x
)
for
l
in
hashresolves
.
keys
():
print
(
"%s:"
%
l
)
v
=
hashresolves
[
l
]
for
x
in
v
.
keys
():
print
(
"
\t
%08x -> %s"
%
(
x
,
v
[
x
]))
if
len
(
noresolves
)
>
0
:
print
(
"UNRESOLVED:"
)
for
x
in
noresolves
:
print
(
"
\t
%08x"
%
x
)
return
0
if
__name__
==
'__main__'
:
rv
=
main
()
if
rv
is
None
:
pass