From c0dd0c5834446604965b0be3a9b0bcd78ecf458d Mon Sep 17 00:00:00 2001 From: Amand Tihon Date: Sun, 9 Aug 2009 20:19:02 +0200 Subject: [PATCH] Add support for SHN_COMMON. The SHN_COMMON pseudo-section is used in the symbol tables to reference undefined global variables. If all instances of the symbol are in the pseudo-section SHN_COMMON, space is reserved in .bss. If the variable is actualy defined, and ends up as GLOBAL in one object, no space is reserved in .bss, and the defined instance is used. --- Bold/elf.py | 10 ++++++++-- Bold/linker.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Bold/elf.py b/Bold/elf.py index 1d73ec7..0ff4602 100644 --- a/Bold/elf.py +++ b/Bold/elf.py @@ -40,6 +40,7 @@ class Elf64(object): self.local_symbols = {} self.global_symbols = {} self.undefined_symbols = [] + self.common_symbols = [] if path: self.filename = path @@ -106,6 +107,11 @@ class Elf64(object): continue if symbol.st_shndx == SHN_ABS: continue + if symbol.st_shndx == SHN_COMMON: + if symbol.name: + sym = (symbol.name, symbol.st_size, symbol.st_value) + self.common_symbols.append(sym) + continue if symbol.st_shndx == SHN_UNDEF: if symbol.name: self.undefined_symbols.append(symbol.name) @@ -132,8 +138,8 @@ class Elf64(object): target = sh.target.content for reloc in sh.content.relatab: - if reloc.symbol.st_shndx == SHN_UNDEF: - # This is an extern symbol, find it in all_global_symbols + if reloc.symbol.st_shndx in [SHN_UNDEF, SHN_COMMON]: + # This is an extern or common symbol, find it in all_global_symbols sym_address = all_global_symbols[reloc.symbol.name] else: # source == in which section it is defined diff --git a/Bold/linker.py b/Bold/linker.py index 505e2f1..0f447c1 100644 --- a/Bold/linker.py +++ b/Bold/linker.py @@ -47,6 +47,7 @@ class BoldLinker(object): self.output = Elf64() self.global_symbols = {} self.undefined_symbols = set() + self.common_symbols = set() def add_object(self, filename): @@ -63,9 +64,10 @@ class BoldLinker(object): """Find out the globally available symbols, as well as the globally undefined ones (which should be found in external libraries.""" - # Gather the "extern" symbols from each input files. + # Gather the "extern" and common symbols from each input files. for i in self.objs: self.undefined_symbols.update(i.undefined_symbols) + self.common_symbols.update(i.common_symbols) # Make a dict with all the symbols declared globally. # Key is the symbol name, value will later be set to the final @@ -84,6 +86,14 @@ class BoldLinker(object): # Find out which symbols aren't really defined anywhere self.undefined_symbols.difference_update(self.global_symbols) + # A symbol declared as COMMON in one object may very well have been + # defined in another. In this case, it will be present in the + # global_symbols. + # Take a copy because we can't change the set's size inside the loop + for i in self.common_symbols.copy(): + if i[0] in self.global_symbols: + self.common_symbols.remove(i) + def build_external(self, with_jump=False, align_jump=False): """ @@ -115,10 +125,17 @@ class BoldLinker(object): fo.shdrs.append(data_shdr) fo.sections['.data'] = data_shdr + # .bss will contain pointers to resolved external functions, as well as + # the COMMON symbols (from C tentative declaration). + bss_size = len(symbols) * 8 + for s_name, s_size, s_alignment in self.common_symbols: + padding = (s_alignment - (bss_size % s_alignment)) + bss_size += padding + s_size + bss_shdr = Elf64_Shdr() bss_shdr.sh_type = SHT_NOBITS bss_shdr.sh_flags = (SHF_WRITE | SHF_ALLOC) - bss_shdr.sh_size = len(symbols) * 8 + bss_shdr.sh_size = bss_size bss_shdr.content = BinArray("") fo.shdrs.append(bss_shdr) fo.sections['.bss'] = bss_shdr @@ -145,6 +162,15 @@ class BoldLinker(object): fo.global_symbols['_bold__functions_hash'] = (data_shdr, 0) fo.global_symbols['_bold__functions_pointers'] = (bss_shdr, 0) + # The COMMON symbols. Assign an offset in .bss, declare as global. + bss_common_offset = len(symbols) * 8 + for s_name, s_size, s_alignment in self.common_symbols: + padding = (s_alignment - (bss_common_offset % s_alignment)) + bss_common_offset += padding + fo.global_symbols[s_name] = (bss_shdr, bss_common_offset) + bss_common_offset += s_size + + for n, i in enumerate(symbols): # The hash is always in .data h = "_bold__hash_%s" % i -- 2.39.5