Skip to content

Commit 4b8c3ac

Browse files
author
Stefan Bossbaly
committed
[HWASan] Fix symbol indexing
Previously we would add any ELF that contained a build id regardless whether the ELF contained symbols or not. This works for Android since soong will strip the symbols into a new directory. However other build systems, like BUCK, will write the stripped file in the same directory as the unstripped file. This would cause the hwasan_symbolize script sometimes add then stripped ELF to its index and ignore the symbolized ELF. The logic has now been changed to only add ELFs that contain symbols to the index. If two symbolized ELFs are encountered with the same build id, we now exit out with an error. Fixes #135966
1 parent d3153ad commit 4b8c3ac

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

compiler-rt/lib/hwasan/scripts/hwasan_symbolize

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Shdr_size = 64
4242
sh_type_offset = 4
4343
sh_offset_offset = 24
4444
sh_size_offset = 32
45+
SHT_SYMTAB = 2
4546
SHT_NOTE = 7
4647

4748
Nhdr_size = 12
@@ -62,8 +63,13 @@ def handle_Nhdr(mv, sh_size):
6263
offset += Nhdr_size + align_up(n_namesz, 4) + align_up(n_descsz, 4)
6364
return None
6465

65-
def handle_Shdr(mv):
66+
def unpack_sh_type(mv):
6667
sh_type, = struct.unpack_from('<I', buffer=mv, offset=sh_type_offset)
68+
return sh_type
69+
70+
def handle_Shdr(mv):
71+
sh_type = unpack_sh_type(mv)
72+
# Sanity check
6773
if sh_type != SHT_NOTE:
6874
return None, None
6975
sh_offset, = struct.unpack_from('<Q', buffer=mv, offset=sh_offset_offset)
@@ -76,19 +82,29 @@ def handle_elf(mv):
7682
# have to extend the parsing code.
7783
if mv[:6] != b'\x7fELF\x02\x01':
7884
return None
85+
found_symbols = False
86+
bid = None
7987
e_shnum, = struct.unpack_from('<H', buffer=mv, offset=e_shnum_offset)
8088
e_shoff, = struct.unpack_from('<Q', buffer=mv, offset=e_shoff_offset)
8189
for i in range(0, e_shnum):
8290
start = e_shoff + i * Shdr_size
83-
sh_offset, sh_size = handle_Shdr(mv[start: start + Shdr_size])
84-
if sh_offset is None:
85-
continue
86-
note_hdr = mv[sh_offset: sh_offset + sh_size]
87-
result = handle_Nhdr(note_hdr, sh_size)
88-
if result is not None:
89-
return result
91+
sh = mv[start: start + Shdr_size]
92+
sh_type = unpack_sh_type(sh)
93+
94+
if sh_type == SHT_SYMTAB:
95+
found_symbols = True
96+
elif sh_type == SHT_NOTE:
97+
sh_offset, sh_size = handle_Shdr(sh)
98+
if sh_offset is None:
99+
continue
100+
note_hdr = mv[sh_offset: sh_offset + sh_size]
101+
result = handle_Nhdr(note_hdr, sh_size)
102+
if result is not None:
103+
bid = result
104+
105+
return (found_symbols, bid)
90106

91-
def get_buildid(filename):
107+
def read_elf(filename):
92108
with open(filename, "r") as fd:
93109
if os.fstat(fd.fileno()).st_size < Ehdr_size:
94110
return None
@@ -200,7 +216,7 @@ class Symbolizer:
200216
if os.path.exists(full_path):
201217
return full_path
202218
if name not in self.__warnings:
203-
print("Could not find symbols for", name, file=sys.stderr)
219+
print("Could not find symbols for {} (Build ID: {})".format(name, buildid), file=sys.stderr)
204220
self.__warnings.add(name)
205221
return None
206222

@@ -268,13 +284,16 @@ class Symbolizer:
268284
for fn in fnames:
269285
filename = os.path.join(dname, fn)
270286
try:
271-
bid = get_buildid(filename)
287+
found_symbols, bid = read_elf(filename)
272288
except FileNotFoundError:
273289
continue
274290
except Exception as e:
275291
print("Failed to parse {}: {}".format(filename, e), file=sys.stderr)
276292
continue
277-
if bid is not None:
293+
if found_symbols and bid is not None:
294+
if bid in self.__index:
295+
print("Duplicate build ID {} for {} and {}".format(bid, self.__index[bid], filename), file=sys.stderr)
296+
sys.exit(1)
278297
self.__index[bid] = filename
279298

280299
def symbolize_line(self, line):

0 commit comments

Comments
 (0)