[haiku-commits] r39646 - in haiku/trunk: headers/private/kernel src/system/kernel

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 26 Nov 2010 14:32:25 +0100 (CET)

Author: bonefish
Date: 2010-11-26 14:32:24 +0100 (Fri, 26 Nov 2010)
New Revision: 39646
Changeset: http://dev.haiku-os.org/changeset/39646

Modified:
   haiku/trunk/headers/private/kernel/elf_priv.h
   haiku/trunk/src/system/kernel/elf.cpp
Log:
* elf_find_symbol(): Skip undefined symbols and symbols with the wrong binding.
* Implemented missing handling of symbolically linked images and of weak
  symbols.


Modified: haiku/trunk/headers/private/kernel/elf_priv.h
===================================================================
--- haiku/trunk/headers/private/kernel/elf_priv.h       2010-11-26 13:24:10 UTC 
(rev 39645)
+++ haiku/trunk/headers/private/kernel/elf_priv.h       2010-11-26 13:32:24 UTC 
(rev 39646)
@@ -34,6 +34,8 @@
        addr_t          dynamic_section;                // pointer to the 
dynamic section
        struct elf_linked_image *linked_images;
 
+       bool            symbolic;
+
        struct Elf32_Ehdr *elf_header;
 
        // pointer to symbol participation data structures

Modified: haiku/trunk/src/system/kernel/elf.cpp
===================================================================
--- haiku/trunk/src/system/kernel/elf.cpp       2010-11-26 13:24:10 UTC (rev 
39645)
+++ haiku/trunk/src/system/kernel/elf.cpp       2010-11-26 13:32:24 UTC (rev 
39646)
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <ctype.h>
 
+#include <algorithm>
+
 #include <AutoDeleter.h>
 #include <boot/kernel_args.h>
 #include <debug.h>
@@ -603,8 +605,14 @@
        for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
                        i = HASHCHAINS(image)[i]) {
                Elf32_Sym* symbol = &image->syms[i];
-               if (strcmp(SYMNAME(image, symbol), name) != 0)
+
+               // consider only symbols with the right name and binding
+               if (symbol->st_shndx == SHN_UNDEF
+                       || ((ELF32_ST_BIND(symbol->st_info) != STB_GLOBAL)
+                               && (ELF32_ST_BIND(symbol->st_info) != STB_WEAK))
+                       || strcmp(SYMNAME(image, symbol), name) != 0) {
                        continue;
+               }
 
                // check the version
 
@@ -767,6 +775,16 @@
                        case DT_VERNEEDNUM:
                                image->num_needed_versions = d[i].d_un.d_val;
                                break;
+                       case DT_SYMBOLIC:
+                               image->symbolic = true;
+                               break;
+                       case DT_FLAGS:
+                       {
+                               uint32 flags = d[i].d_un.d_val;
+                               if ((flags & DF_SYMBOLIC) != 0)
+                                       image->symbolic = true;
+                               break;
+                       }
 
                        default:
                                continue;
@@ -979,7 +997,13 @@
                return B_OK;
        }
 
-       // Non-local symbols we try to resolve to the kernel image first.
+       // Non-local symbols we try to resolve to the kernel image first. Unless
+       // the image is linked symbolically, then vice versa.
+       elf_image_info* firstImage = sharedImage;
+       elf_image_info* secondImage = image;
+       if (image->symbolic)
+               std::swap(firstImage, secondImage);
+
        const char *symbolName = SYMNAME(image, symbol);
 
        // get the version info
@@ -992,13 +1016,23 @@
        }
 
        // find the symbol
-       elf_image_info* foundImage = sharedImage;
-       struct Elf32_Sym* foundSymbol = elf_find_symbol(sharedImage, symbolName,
+       elf_image_info* foundImage = firstImage;
+       struct Elf32_Sym* foundSymbol = elf_find_symbol(firstImage, symbolName,
                versionInfo, false);
-       if (foundSymbol == NULL) {
-               // not found yet, try to resolve in the requesting image
-               foundImage = image;
-               foundSymbol = elf_find_symbol(image, symbolName, versionInfo, 
false);
+       if (foundSymbol == NULL
+               || ELF32_ST_BIND(foundSymbol->st_info) == STB_WEAK) {
+               // Not found or found a weak definition -- try to resolve in 
the other
+               // image.
+               Elf32_Sym* secondSymbol = elf_find_symbol(secondImage, 
symbolName,
+                       versionInfo, false);
+               // If we found a symbol -- take it in case we didn't have a 
symbol
+               // before or the new symbol is not weak.
+               if (secondSymbol != NULL
+                       && (foundSymbol == NULL
+                               || ELF32_ST_BIND(secondSymbol->st_info) != 
STB_WEAK)) {
+                       foundImage = secondImage;
+                       foundSymbol = secondSymbol;
+               }
        }
 
        if (foundSymbol == NULL) {
@@ -1015,18 +1049,14 @@
 
        // make sure they're the same type
        if (ELF32_ST_TYPE(symbol->st_info) != 
ELF32_ST_TYPE(foundSymbol->st_info)) {
-               dprintf("elf_resolve_symbol: found symbol '%s' in shared image "
-                       "but wrong type\n", symbolName);
+               dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
+                       "(requested by image '%s') but wrong type (%d vs. 
%d)\n",
+                       symbolName, foundImage->name, image->name,
+                       ELF32_ST_TYPE(foundSymbol->st_info),
+                       ELF32_ST_TYPE(symbol->st_info));
                return B_MISSING_SYMBOL;
        }
 
-       if (ELF32_ST_BIND(foundSymbol->st_info) != STB_GLOBAL
-               && ELF32_ST_BIND(foundSymbol->st_info) != STB_WEAK) {
-               TRACE(("elf_resolve_symbol: found symbol '%s' but not 
exported\n",
-                       symbolName));
-               return B_MISSING_SYMBOL;
-       }
-
        *_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta;
        return B_OK;
 }


Other related posts:

  • » [haiku-commits] r39646 - in haiku/trunk: headers/private/kernel src/system/kernel - ingo_weinhold