/
/
Copyright
(
c
)
2011
Google
Inc
.
/
/
All
rights
reserved
.
/
/
/
/
Redistribution
and
use
in
source
and
binary
forms
with
or
without
/
/
modification
are
permitted
provided
that
the
following
conditions
are
/
/
met
:
/
/
/
/
*
Redistributions
of
source
code
must
retain
the
above
copyright
/
/
notice
this
list
of
conditions
and
the
following
disclaimer
.
/
/
*
Redistributions
in
binary
form
must
reproduce
the
above
/
/
copyright
notice
this
list
of
conditions
and
the
following
disclaimer
/
/
in
the
documentation
and
/
or
other
materials
provided
with
the
/
/
distribution
.
/
/
*
Neither
the
name
of
Google
Inc
.
nor
the
names
of
its
/
/
contributors
may
be
used
to
endorse
or
promote
products
derived
from
/
/
this
software
without
specific
prior
written
permission
.
/
/
/
/
THIS
SOFTWARE
IS
PROVIDED
BY
THE
COPYRIGHT
HOLDERS
AND
CONTRIBUTORS
/
/
"
AS
IS
"
AND
ANY
EXPRESS
OR
IMPLIED
WARRANTIES
INCLUDING
BUT
NOT
/
/
LIMITED
TO
THE
IMPLIED
WARRANTIES
OF
MERCHANTABILITY
AND
FITNESS
FOR
/
/
A
PARTICULAR
PURPOSE
ARE
DISCLAIMED
.
IN
NO
EVENT
SHALL
THE
COPYRIGHT
/
/
OWNER
OR
CONTRIBUTORS
BE
LIABLE
FOR
ANY
DIRECT
INDIRECT
INCIDENTAL
/
/
SPECIAL
EXEMPLARY
OR
CONSEQUENTIAL
DAMAGES
(
INCLUDING
BUT
NOT
/
/
LIMITED
TO
PROCUREMENT
OF
SUBSTITUTE
GOODS
OR
SERVICES
;
LOSS
OF
USE
/
/
DATA
OR
PROFITS
;
OR
BUSINESS
INTERRUPTION
)
HOWEVER
CAUSED
AND
ON
ANY
/
/
THEORY
OF
LIABILITY
WHETHER
IN
CONTRACT
STRICT
LIABILITY
OR
TORT
/
/
(
INCLUDING
NEGLIGENCE
OR
OTHERWISE
)
ARISING
IN
ANY
WAY
OUT
OF
THE
USE
/
/
OF
THIS
SOFTWARE
EVEN
IF
ADVISED
OF
THE
POSSIBILITY
OF
SUCH
DAMAGE
.
/
/
Original
author
:
Ted
Mielczarek
<
ted
.
mielczarek
gmail
.
com
>
/
/
dump_symbols_unittest
.
cc
:
/
/
Unittests
for
google_breakpad
:
:
DumpSymbols
#
include
<
elf
.
h
>
#
include
<
link
.
h
>
#
include
<
stdio
.
h
>
#
include
<
sstream
>
#
include
<
vector
>
#
include
"
breakpad_googletest_includes
.
h
"
#
include
"
common
/
linux
/
elf_gnu_compat
.
h
"
#
include
"
common
/
linux
/
elfutils
.
h
"
#
include
"
common
/
linux
/
dump_symbols
.
h
"
#
include
"
common
/
linux
/
synth_elf
.
h
"
#
include
"
common
/
module
.
h
"
#
include
"
common
/
using_std_string
.
h
"
namespace
google_breakpad
{
bool
ReadSymbolDataInternal
(
const
uint8_t
*
obj_file
const
string
&
obj_filename
const
string
&
obj_os
const
std
:
:
vector
<
string
>
&
debug_dir
const
DumpOptions
&
options
Module
*
*
module
)
;
using
google_breakpad
:
:
synth_elf
:
:
ELF
;
using
google_breakpad
:
:
synth_elf
:
:
Notes
;
using
google_breakpad
:
:
synth_elf
:
:
StringTable
;
using
google_breakpad
:
:
synth_elf
:
:
SymbolTable
;
using
google_breakpad
:
:
test_assembler
:
:
kLittleEndian
;
using
google_breakpad
:
:
test_assembler
:
:
Section
;
using
std
:
:
stringstream
;
using
std
:
:
vector
;
using
:
:
testing
:
:
Test
;
using
:
:
testing
:
:
Types
;
template
<
typename
ElfClass
>
class
DumpSymbols
:
public
Test
{
public
:
void
GetElfContents
(
ELF
&
elf
)
{
string
contents
;
ASSERT_TRUE
(
elf
.
GetContents
(
&
contents
)
)
;
ASSERT_LT
(
0U
contents
.
size
(
)
)
;
elfdata_v
.
clear
(
)
;
elfdata_v
.
insert
(
elfdata_v
.
begin
(
)
contents
.
begin
(
)
contents
.
end
(
)
)
;
elfdata
=
&
elfdata_v
[
0
]
;
}
vector
<
uint8_t
>
elfdata_v
;
uint8_t
*
elfdata
;
}
;
typedef
Types
<
ElfClass32
ElfClass64
>
ElfClasses
;
TYPED_TEST_SUITE
(
DumpSymbols
ElfClasses
)
;
TYPED_TEST
(
DumpSymbols
Invalid
)
{
Elf32_Ehdr
header
;
memset
(
&
header
0
sizeof
(
header
)
)
;
Module
*
module
;
DumpOptions
options
(
ALL_SYMBOL_DATA
true
)
;
EXPECT_FALSE
(
ReadSymbolDataInternal
(
reinterpret_cast
<
uint8_t
*
>
(
&
header
)
"
foo
"
"
Linux
"
vector
<
string
>
(
)
options
&
module
)
)
;
}
TYPED_TEST
(
DumpSymbols
SimplePublic
)
{
ELF
elf
(
TypeParam
:
:
kMachine
TypeParam
:
:
kClass
kLittleEndian
)
;
/
/
Zero
out
text
section
for
simplicity
.
Section
text
(
kLittleEndian
)
;
text
.
Append
(
4096
0
)
;
elf
.
AddSection
(
"
.
text
"
text
SHT_PROGBITS
)
;
/
/
Add
a
public
symbol
.
StringTable
table
(
kLittleEndian
)
;
SymbolTable
syms
(
kLittleEndian
TypeParam
:
:
kAddrSize
table
)
;
syms
.
AddSymbol
(
"
superfunc
"
(
typename
TypeParam
:
:
Addr
)
0x1000
(
typename
TypeParam
:
:
Addr
)
0x10
/
/
ELF32_ST_INFO
works
for
32
-
or
64
-
bit
.
ELF32_ST_INFO
(
STB_GLOBAL
STT_FUNC
)
SHN_UNDEF
+
1
)
;
int
index
=
elf
.
AddSection
(
"
.
dynstr
"
table
SHT_STRTAB
)
;
elf
.
AddSection
(
"
.
dynsym
"
syms
SHT_DYNSYM
/
/
type
SHF_ALLOC
/
/
flags
0
/
/
addr
index
/
/
link
sizeof
(
typename
TypeParam
:
:
Sym
)
)
;
/
/
entsize
elf
.
Finish
(
)
;
this
-
>
GetElfContents
(
elf
)
;
Module
*
module
;
DumpOptions
options
(
ALL_SYMBOL_DATA
true
)
;
EXPECT_TRUE
(
ReadSymbolDataInternal
(
this
-
>
elfdata
"
foo
"
"
Linux
"
vector
<
string
>
(
)
options
&
module
)
)
;
stringstream
s
;
module
-
>
Write
(
s
ALL_SYMBOL_DATA
)
;
const
string
expected
=
string
(
"
MODULE
Linux
"
)
+
TypeParam
:
:
kMachineName
+
"
000000000000000000000000000000000
foo
\
n
"
"
INFO
CODE_ID
00000000000000000000000000000000
\
n
"
"
PUBLIC
1000
0
superfunc
\
n
"
;
EXPECT_EQ
(
expected
s
.
str
(
)
)
;
delete
module
;
}
TYPED_TEST
(
DumpSymbols
SimpleBuildID
)
{
ELF
elf
(
TypeParam
:
:
kMachine
TypeParam
:
:
kClass
kLittleEndian
)
;
/
/
Zero
out
text
section
for
simplicity
.
Section
text
(
kLittleEndian
)
;
text
.
Append
(
4096
0
)
;
elf
.
AddSection
(
"
.
text
"
text
SHT_PROGBITS
)
;
/
/
Add
a
Build
ID
const
uint8_t
kExpectedIdentifierBytes
[
]
=
{
0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08
0x09
0x0A
0x0B
0x0C
0x0D
0x0E
0x0F
0x10
0x11
0x12
0x13
}
;
Notes
notes
(
kLittleEndian
)
;
notes
.
AddNote
(
NT_GNU_BUILD_ID
"
GNU
"
kExpectedIdentifierBytes
sizeof
(
kExpectedIdentifierBytes
)
)
;
elf
.
AddSection
(
"
.
note
.
gnu
.
build
-
id
"
notes
SHT_NOTE
)
;
/
/
Add
a
public
symbol
.
StringTable
table
(
kLittleEndian
)
;
SymbolTable
syms
(
kLittleEndian
TypeParam
:
:
kAddrSize
table
)
;
syms
.
AddSymbol
(
"
superfunc
"
(
typename
TypeParam
:
:
Addr
)
0x1000
(
typename
TypeParam
:
:
Addr
)
0x10
/
/
ELF32_ST_INFO
works
for
32
-
or
64
-
bit
.
ELF32_ST_INFO
(
STB_GLOBAL
STT_FUNC
)
SHN_UNDEF
+
1
)
;
int
index
=
elf
.
AddSection
(
"
.
dynstr
"
table
SHT_STRTAB
)
;
elf
.
AddSection
(
"
.
dynsym
"
syms
SHT_DYNSYM
/
/
type
SHF_ALLOC
/
/
flags
0
/
/
addr
index
/
/
link
sizeof
(
typename
TypeParam
:
:
Sym
)
)
;
/
/
entsize
elf
.
Finish
(
)
;
this
-
>
GetElfContents
(
elf
)
;
Module
*
module
;
DumpOptions
options
(
ALL_SYMBOL_DATA
true
)
;
EXPECT_TRUE
(
ReadSymbolDataInternal
(
this
-
>
elfdata
"
foo
"
"
Linux
"
vector
<
string
>
(
)
options
&
module
)
)
;
stringstream
s
;
module
-
>
Write
(
s
ALL_SYMBOL_DATA
)
;
const
string
expected
=
string
(
"
MODULE
Linux
"
)
+
TypeParam
:
:
kMachineName
+
"
030201000504070608090A0B0C0D0E0F0
foo
\
n
"
"
INFO
CODE_ID
000102030405060708090A0B0C0D0E0F10111213
\
n
"
"
PUBLIC
1000
0
superfunc
\
n
"
;
EXPECT_EQ
(
expected
s
.
str
(
)
)
;
delete
module
;
}
}
/
/
namespace
google_breakpad
