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.
self.local_symbols = {}
self.global_symbols = {}
self.undefined_symbols = []
self.local_symbols = {}
self.global_symbols = {}
self.undefined_symbols = []
+ self.common_symbols = []
if path:
self.filename = path
if path:
self.filename = path
continue
if symbol.st_shndx == SHN_ABS:
continue
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)
if symbol.st_shndx == SHN_UNDEF:
if symbol.name:
self.undefined_symbols.append(symbol.name)
target = sh.target.content
for reloc in sh.content.relatab:
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
sym_address = all_global_symbols[reloc.symbol.name]
else:
# source == in which section it is defined
self.output = Elf64()
self.global_symbols = {}
self.undefined_symbols = set()
self.output = Elf64()
self.global_symbols = {}
self.undefined_symbols = set()
+ self.common_symbols = set()
def add_object(self, filename):
def add_object(self, filename):
"""Find out the globally available symbols, as well as the globally
undefined ones (which should be found in external libraries."""
"""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)
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
# Make a dict with all the symbols declared globally.
# Key is the symbol name, value will later be set to the final
# Find out which symbols aren't really defined anywhere
self.undefined_symbols.difference_update(self.global_symbols)
# 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):
"""
def build_external(self, with_jump=False, align_jump=False):
"""
fo.shdrs.append(data_shdr)
fo.sections['.data'] = data_shdr
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 = 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
bss_shdr.content = BinArray("")
fo.shdrs.append(bss_shdr)
fo.sections['.bss'] = bss_shdr
fo.global_symbols['_bold__functions_hash'] = (data_shdr, 0)
fo.global_symbols['_bold__functions_pointers'] = (bss_shdr, 0)
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
for n, i in enumerate(symbols):
# The hash is always in .data
h = "_bold__hash_%s" % i