]> git.alrj.org Git - bold.git/commitdiff
Add support for SHN_COMMON.
authorAmand Tihon <amand.tihon@alrj.org>
Sun, 9 Aug 2009 18:19:02 +0000 (20:19 +0200)
committerAmand Tihon <amand.tihon@alrj.org>
Sat, 15 Aug 2009 18:19:19 +0000 (20:19 +0200)
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
Bold/linker.py

index 1d73ec7175c5db71dc12f2fbcb8b9f7932818787..0ff4602bab1cd736cbb71dd1d51410e8f77b2e9d 100644 (file)
@@ -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
index 505e2f130f3f3c1a7863a08d36a301119ad250d9..0f447c1a8f470067ada9e65f504111a285f1a0e7 100644 (file)
@@ -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