aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxetc
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2022-10-30 08:28:44 +0100
committerspicyjpeg <thatspicyjpeg@gmail.com>2022-10-30 08:28:44 +0100
commit68daf6d338aba6e32e687d4151eaddc8735227b3 (patch)
tree8cb84440219dd8041c4e84219c3742561d020819 /libpsn00b/psxetc
parentf6c41f3783c4fce49a9899b710ebb50ba9f647ab (diff)
downloadpsn00bsdk-68daf6d338aba6e32e687d4151eaddc8735227b3.tar.gz
Refactor dynamic linker, misc. cleanups
Diffstat (limited to 'libpsn00b/psxetc')
-rw-r--r--libpsn00b/psxetc/dl.c399
1 files changed, 131 insertions, 268 deletions
diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c
index fa5e74d..ccf7a7c 100644
--- a/libpsn00b/psxetc/dl.c
+++ b/libpsn00b/psxetc/dl.c
@@ -1,6 +1,6 @@
/*
* PSn00bSDK dynamic linker
- * (C) 2021 spicyjpeg - MPL licensed
+ * (C) 2021-2022 spicyjpeg - MPL licensed
*
* The bulk of this code is MIPS-specific but not PS1-specific, so the whole
* dynamic linker could be ported to other MIPS platforms that do not have one
@@ -27,8 +27,10 @@
#define SDK_LIBRARY_NAME "psxetc/dl"
#include <stdint.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <elf.h>
@@ -36,13 +38,6 @@
#include <string.h>
#include <psxapi.h>
-/* Compile options */
-
-// Comment before building to disable functions that rely on BIOS file APIs,
-// i.e. DL_LoadSymbolMapFromFile() and DL_LoadDLLFromFile().
-// FIXME: those seem to be broken currently, and shouldn't be used anyway
-//#define USE_FILE_API
-
/* Private types */
typedef struct {
@@ -51,17 +46,15 @@ typedef struct {
} MapEntry;
typedef struct {
- uint32_t nbucket;
- uint32_t nchain;
+ int nbucket, nchain, index;
MapEntry *entries;
uint32_t *bucket;
uint32_t *chain;
} SymbolMap;
-/* Data */
+/* Internal globals */
-static DL_Error _error_code = RTLD_E_NONE;
static SymbolMap _symbol_map;
// Accessed by _dl_resolve_helper, stores the pointer to the current resolver
@@ -70,11 +63,6 @@ void *(*_dl_resolve_callback)(DLL *, const char *) = 0;
/* Private utilities */
-#define _ERROR(code, ret) { \
- _error_code = code; \
- return ret; \
-}
-
void _dl_resolve_wrapper(void);
// Called by _dl_resolve_wrapper() (which is in turn called by GCC stubs) to
@@ -82,29 +70,28 @@ void _dl_resolve_wrapper(void);
void *_dl_resolve_helper(DLL *dll, uint32_t index) {
Elf32_Sym *sym = &(dll->symtab[index]);
const char *_name = &(dll->strtab[sym->st_name]);
- void *address;
+ void *addr;
if (_dl_resolve_callback)
- address = _dl_resolve_callback(dll, _name);
+ addr = _dl_resolve_callback(dll, _name);
else
- address = DL_GetSymbolByName(_name);
+ addr = DL_GetMapSymbol(_name);
- if (!address) {
- _sdk_log("FATAL! can't resolve %s, locking up\n", _name);
- while (1)
- __asm__ volatile("nop");
+ if (!addr) {
+ _sdk_log("FATAL! can't resolve %s, aborting\n", _name);
+ abort();
}
// Patch the GOT entry to "cache" the resolved address. This can probably
// be implemented in a faster way, but this thing is already too complex.
- for (uint32_t i = 0; i < dll->got_length; i++) {
+ for (int i = 0; i < dll->got_length; i++) {
if (dll->got[2 + i] == (uint32_t) sym->st_value) {
- dll->got[2 + i] = (uint32_t) address;
+ dll->got[2 + i] = (uint32_t) addr;
break;
}
}
- return address;
+ return addr;
}
// Implementation of the weird obscure hashing function used in the ELF .hash
@@ -127,120 +114,109 @@ static uint32_t _elf_hash(const char *str) {
return value;
}
-#ifdef USE_FILE_API
-static uint8_t *_dl_load_file(const char *filename, size_t *size_output) {
- int32_t fd = open(filename, 1);
- if (fd < 0) {
- _sdk_log("can't open %s, error = %d\n", filename, fd);
- _ERROR(RTLD_E_FILE_OPEN, 0);
- }
+/* Symbol map loading/introspection API */
- // Extract file size from the file's associated control block.
- // https://problemkaputt.de/psx-spx.htm#biosmemorymap
- FCB *fcb = (FCB *) *((FCB **) 0x80000140);
- size_t size = fcb[fd].filesize;
+int DL_InitSymbolMap(int num_entries) {
+ if (_symbol_map.entries)
+ DL_UnloadSymbolMap();
- uint8_t *buffer = malloc(size);
- if (!buffer) {
- _sdk_log("unable to allocate %d bytes for %s\n", size, filename);
- _ERROR(RTLD_E_FILE_ALLOC, 0);
- }
+ // TODO: find a way to calculate the optimal number of hash table "buckets"
+ // in order to minimize hash table size
+ _symbol_map.nbucket = num_entries;
+ _symbol_map.nchain = num_entries;
+ _symbol_map.index = 0;
+ _sdk_log(
+ "allocating nbucket = %d, nchain = %d\n",
+ _symbol_map.nbucket, num_entries
+ );
- //_sdk_log("loading %s (%d bytes)..", filename, size);
+ _symbol_map.entries = malloc(sizeof(MapEntry) * num_entries);
+ _symbol_map.bucket = malloc(sizeof(uint32_t) * num_entries);
+ _symbol_map.chain = malloc(sizeof(uint32_t) * num_entries);
- for (uint32_t offset = 0; offset < size; ) {
- int32_t length = read(fd, &(buffer[offset]), 0x800);
+ if (!_symbol_map.entries || !_symbol_map.bucket || !_symbol_map.chain) {
+ _sdk_log("unable to allocate symbol map table\n");
+ return -1;
+ }
- if (length <= 0) {
- close(fd);
- free(buffer);
+ memset(_symbol_map.bucket, 0xff, sizeof(uint32_t) * num_entries);
+ memset(_symbol_map.chain, 0xff, sizeof(uint32_t) * num_entries);
- _sdk_log("failed, error = %d\n", length);
- _ERROR(RTLD_E_FILE_READ, 0);
- }
+ return 0;
+}
- //_sdk_log(".");
- offset += length;
- }
+void DL_UnloadSymbolMap(void) {
+ if (!_symbol_map.entries)
+ return;
- close(fd);
- _sdk_log(" done\n");
+ free(_symbol_map.entries);
+ free(_symbol_map.bucket);
+ free(_symbol_map.chain);
- if (size_output)
- *size_output = size;
- return buffer;
+ _symbol_map.entries = 0;
+ _symbol_map.bucket = 0;
+ _symbol_map.chain = 0;
}
-#endif
-/* Symbol map loading/parsing API */
+void DL_AddMapSymbol(const char *name, void *ptr) {
+ uint32_t hash = _elf_hash(name);
+ int index = _symbol_map.index;
+ _symbol_map.index = index + 1;
-int32_t DL_ParseSymbolMap(const char *ptr, size_t size) {
- DL_UnloadSymbolMap();
+ MapEntry *entry = &(_symbol_map.entries[index]);
+ entry->hash = hash;
+ entry->ptr = ptr;
+
+ // Append a reference to the entry to the hash table's chain.
+ uint32_t *hash_entry = &(_symbol_map.bucket[hash % _symbol_map.nbucket]);
+ while (*hash_entry != 0xffffffff)
+ hash_entry = &(_symbol_map.chain[*hash_entry]);
+
+ *hash_entry = index;
+}
+
+int DL_ParseSymbolMap(const char *ptr, size_t size) {
+ int entries = 0;
// Perform a quick scan over the entire map text and count the number of
// newlines. This allows us to (over)estimate the number of entries and
- // allocate a sufficiently large hash/entry table.
- uint32_t entries = 0;
- for (uint32_t pos = 0; pos < size; pos++) {
+ // allocate a sufficiently large hash table.
+ for (int pos = 0; pos < size; pos++) {
if (ptr[pos] == '\n')
entries++;
}
- // TODO: find a way to calculate the optimal number of hash table "buckets"
- // in order to minimize hash table size
- _symbol_map.nbucket = entries;
- _symbol_map.nchain = entries;
- _sdk_log(
- "allocating nbucket = %d, nchain = %d\n",
- _symbol_map.nbucket,
- entries
- );
-
- // Allocate an entry table to store parsed symbols in, and an associated
- // hash table (same format as .hash section, with 8-byte header).
- _symbol_map.entries = malloc(sizeof(MapEntry) * entries);
- _symbol_map.bucket = malloc(sizeof(uint32_t) * _symbol_map.nbucket);
- _symbol_map.chain = malloc(sizeof(uint32_t) * entries);
+ int err = DL_InitSymbolMap(entries);
+ if (err)
+ return err;
- if (!_symbol_map.entries || !_symbol_map.bucket || !_symbol_map.chain) {
- _sdk_log("unable to allocate symbol map table\n");
- _ERROR(RTLD_E_MAP_ALLOC, -1);
- }
+ // Go again through the symbol map and fill in the hash table by calling
+ // DL_AddMapSymbol() for each valid entry.
+ entries = 0;
- for (uint32_t i = 0; i < _symbol_map.nbucket; i++)
- _symbol_map.bucket[i] = 0xffffffff;
- for (uint32_t i = 0; i < entries; i++)
- _symbol_map.chain[i] = 0xffffffff;
-
- // Go again through the symbol map and fill in the hash table.
- uint32_t index = 0;
- for (uint32_t pos = 0; (pos < size) && ptr[pos]; pos++) {
- char name[64];
- char type_string[2];
- uint64_t address64;
+ for (int pos = 0; (pos < size) && ptr[pos]; pos++) {
+ uint64_t full_addr;
+ char name[64], type_string[4];
size_t _size;
// e.g. "main T ffffffff80000000 100 ...\n"
- int32_t parsed = sscanf(
+ int parsed = sscanf(
&(ptr[pos]),
"%63s %1s %Lx %x",
name,
type_string,
- &address64,
+ &full_addr,
&_size // Optional, unused (yet)
);
if (parsed >= 3) {
// Drop the upper 32 bits of the address (for some reason MIPS nm
- // insists on printing 64-bit addresses... wtf) and normalize the
- // type letter to upper case, then check if the entry is valid and
- // non-null.
- void *address = (void *) ((uint32_t) address64);
- char _type = toupper(type_string[0]);
- uint32_t hash = _elf_hash(name);
- uint32_t hash_mod = hash % _symbol_map.nbucket;
-
- if (address && (
+ // insists on printing 64-bit addresses... wtf) and check if the
+ // entry is valid and non-null.
+ void *addr = (void *) ((uint32_t) full_addr);
+ char _type = toupper(type_string[0]);
+
+ if (addr && (
(_type == 'T') || // .text
(_type == 'R') || // .rodata
(_type == 'D') || // .data
@@ -248,21 +224,11 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) {
)) {
//_sdk_log(
//"map sym: %08x,%08x [%c %s]\n",
- //address, _size, _type, name
+ //addr, _size, _type, name
//);
- MapEntry *entry = &(_symbol_map.entries[index]);
- entry->hash = hash;
- entry->ptr = address;
-
- // Append a reference to the entry to the hash table's chain
- // for the current hash_mod. I can't explain this properly.
- uint32_t *hash_entry = &(_symbol_map.bucket[hash_mod]);
- while (*hash_entry != 0xffffffff)
- hash_entry = &(_symbol_map.chain[*hash_entry]);
-
- *hash_entry = index;
- index++;
+ DL_AddMapSymbol(name, addr);
+ entries++;
}
}
@@ -273,55 +239,27 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) {
}
_sdk_log("parsed %d symbols\n", entries);
- if (!entries)
- _ERROR(RTLD_E_NO_SYMBOLS, -1);
-
return entries;
}
-#ifdef USE_FILE_API
-int32_t DL_LoadSymbolMapFromFile(const char *filename) {
- size_t size;
- char *ptr = _dl_load_file(filename, &size);
- if (!ptr)
- return -1;
-
- int32_t entries = DL_ParseSymbolMap(ptr, size);
- free(ptr);
-
- return entries;
-}
-#endif
-
-void DL_UnloadSymbolMap(void) {
- if (!_symbol_map.entries)
- return;
-
- free(_symbol_map.entries);
- free(_symbol_map.bucket);
- free(_symbol_map.chain);
- _symbol_map.entries = 0;
-}
-
-void *DL_GetSymbolByName(const char *name) {
+void *DL_GetMapSymbol(const char *name) {
if (!_symbol_map.entries) {
- _sdk_log("attempted lookup with no map loaded\n");
- _ERROR(RTLD_E_NO_MAP, 0);
+ _sdk_log("DL_GetMapSymbol() with no map loaded\n");
+ return 0;
}
- // https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-48031.html
- uint32_t hash = _elf_hash(name);
- uint32_t hash_mod = hash % _symbol_map.nbucket;
-
// Go through the hash table's chain until the symbol hash matches the one
// calculated.
- for (uint32_t i = _symbol_map.bucket[hash_mod]; i != 0xffffffff;) {
+ // https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-48031.html
+ uint32_t hash = _elf_hash(name);
+
+ for (int i = _symbol_map.bucket[hash % _symbol_map.nbucket]; i != 0xffffffff;) {
if (i >= _symbol_map.nchain) {
_sdk_log(
- "GetSymbolByName() index out of bounds (%d >= %d)\n",
+ "DL_GetMapSymbol() index out of bounds (%d >= %d)\n",
i, _symbol_map.nchain
);
- _ERROR(RTLD_E_HASH_LOOKUP, 0);
+ return 0;
}
MapEntry *entry = &(_symbol_map.entries[i]);
@@ -335,27 +273,24 @@ void *DL_GetSymbolByName(const char *name) {
}
_sdk_log("map lookup [%s not found]\n", name);
- _ERROR(RTLD_E_MAP_SYMBOL, 0);
+ return 0;
}
-void DL_SetResolveCallback(void *(*callback)(DLL *, const char *)) {
+void *DL_SetResolveCallback(void *(*callback)(DLL *, const char *)) {
+ void *old_callback = _dl_resolve_callback;
_dl_resolve_callback = callback;
+
+ return old_callback;
}
/* Library loading and linking API */
-DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
- if (!ptr)
- _ERROR(RTLD_E_DLL_NULL, 0);
-
- DLL *dll = malloc(sizeof(DLL));
- if (!dll) {
- _sdk_log("unable to allocate DLL struct\n");
- _ERROR(RTLD_E_DLL_ALLOC, 0);
- }
+DLL *DL_CreateDLL(DLL *dll, void *ptr, size_t size, DL_ResolveMode mode) {
+ if (!dll || !ptr)
+ return 0;
dll->ptr = ptr;
- dll->malloc_ptr = (mode & RTLD_FREE_ON_DESTROY) ? ptr : 0;
+ dll->malloc_ptr = (mode & DL_FREE_ON_DESTROY) ? ptr : 0;
dll->size = size;
_sdk_log("initializing DLL at %08x\n", ptr);
@@ -371,47 +306,30 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
switch (dyn->d_tag) {
// Offset of .got section
case DT_PLTGOT:
- //_sdk_log("[PLTGOT]\n");
-
dll->got = (void *) (ptr + dyn->d_un.d_val);
break;
// Offset of .hash section
case DT_HASH:
- //_sdk_log("[HASH]\n");
-
dll->hash = (void *) (ptr + dyn->d_un.d_val);
break;
// Offset of .dynstr (NOT .strtab) section
case DT_STRTAB:
- //_sdk_log("[STRTAB]\n");
-
dll->strtab = (void *) (ptr + dyn->d_un.d_val);
break;
// Offset of .dynsym (NOT .symtab) section
case DT_SYMTAB:
- //_sdk_log("[SYMTAB]\n");
-
dll->symtab = (void *) (ptr + dyn->d_un.d_val);
break;
- // Length of .dynstr section
- //case DT_STRSZ:
- //_sdk_log("[STRSZ]\n");
- //break;
-
// Length of each .dynsym entry
case DT_SYMENT:
- //_sdk_log("[SYMENT]\n");
-
// Only 16-byte symbol table entries are supported.
if (dyn->d_un.d_val != sizeof(Elf32_Sym)) {
- free(dll);
-
_sdk_log("invalid DLL symtab entry size %d\n", dyn->d_un.d_val);
- _ERROR(RTLD_E_DLL_FORMAT, 0);
+ return 0;
}
break;
@@ -421,73 +339,44 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
// Versions other than 1 are unsupported (do they even exist?).
if (dyn->d_un.d_val != 1) {
- free(dll);
-
_sdk_log("invalid DLL version %d\n", dyn->d_un.d_val);
- _ERROR(RTLD_E_DLL_FORMAT, 0);
+ return 0;
}
break;
// DLL/ABI flags
case DT_MIPS_FLAGS:
- //_sdk_log("[MIPS_FLAGS]\n");
-
// Shortcut pointers (whatever they are) are not supported.
if (dyn->d_un.d_val & RHF_QUICKSTART) {
- free(dll);
-
_sdk_log("invalid DLL flags\n");
- _ERROR(RTLD_E_DLL_FORMAT, 0);
+ return 0;
}
break;
// Number of local (not to resolve) GOT entries
case DT_MIPS_LOCAL_GOTNO:
- //_sdk_log("[MIPS_LOCAL_GOTNO]\n");
-
local_got_len = dyn->d_un.d_val;
break;
// Base address DLL was compiled for
case DT_MIPS_BASE_ADDRESS:
- //_sdk_log("[MIPS_BASE_ADDRESS]\n");
-
// Base addresses other than zero are not supported. It would
// be easy enough to support them, but why?
if (dyn->d_un.d_val) {
- free(dll);
-
_sdk_log("invalid DLL base address %08x\n", dyn->d_un.d_val);
- _ERROR(RTLD_E_DLL_FORMAT, 0);
+ return 0;
}
break;
// Number of symbol table entries
case DT_MIPS_SYMTABNO:
- //_sdk_log("[MIPS_SYMTABNO]\n");
-
dll->symbol_count = dyn->d_un.d_val;
break;
- // Index of first unresolved symbol table entry
- //case DT_MIPS_UNREFEXTNO:
- //_sdk_log("[MIPS_UNREFEXTNO]\n");
- //break;
-
// Index of first symbol table entry which has a matching GOT entry
case DT_MIPS_GOTSYM:
- //_sdk_log("[MIPS_GOTSYM]\n");
-
first_got_sym = dyn->d_un.d_val;
break;
-
- // Number of pages the GOT is split into (does not apply to PS1)
- //case DT_MIPS_HIPAGENO:
- //_sdk_log("[MIPS_HIPAGENO]\n");
- //break;
-
- //default:
- //_sdk_log("[ignored]\n");
}
}
@@ -513,14 +402,14 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
dll->got[0] = (uint32_t) &_dl_resolve_wrapper;
dll->got[1] = (uint32_t) dll;
- for (uint32_t i = 0; i < dll->got_length; i++)
+ for (int i = 0; i < dll->got_length; i++)
dll->got[2 + i] += (uint32_t) ptr;
// Fix addresses in the symbol table.
// TODO: clean this shit up
uint32_t got_offset = first_got_sym;
- for (uint32_t i = 0; i < dll->symbol_count; i++) {
+ for (int i = 0; i < dll->symbol_count; i++) {
Elf32_Sym *sym = &(dll->symtab[i]);
const char *_name = &(dll->strtab[sym->st_name]);
@@ -533,12 +422,12 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
//sym->st_value, sym->st_size, _name
//);
- // If RTLD_NOW was passed, resolve GOT entries ahead of time by
+ // If DL_NOW was passed, resolve GOT entries ahead of time by
// cross-referencing them with the symbol table.
- if (!(mode & RTLD_NOW))
+ if (!(mode & DL_NOW))
continue;
- for (uint32_t j = got_offset; j < dll->got_length; j++) {
+ for (int j = got_offset; j < dll->got_length; j++) {
if (dll->got[2 + j] != (uint32_t) sym->st_value)
continue;
@@ -553,10 +442,8 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
)) {
dll->got[2 + j] = (uint32_t) _dl_resolve_callback(dll, _name);
- if (!dll->got[2 + j]) {
- free(dll);
- _ERROR(RTLD_E_MAP_SYMBOL, 0);
- }
+ if (!dll->got[2 + j])
+ return 0;
}
break;
@@ -573,7 +460,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
// DLL itself.
const uint32_t *ctor_list = DL_GetDLLSymbol(dll, "__CTOR_LIST__");
if (ctor_list) {
- for (uint32_t i = ((uint32_t) ctor_list[0]); i >= 1; i--) {
+ for (int i = ((int) ctor_list[0]); i >= 1; i--) {
void (*ctor)(void) = (void (*)(void)) ctor_list[i];
DL_PRE_CALL(ctor);
ctor();
@@ -583,64 +470,47 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
return dll;
}
-#ifdef USE_FILE_API
-DLL *DL_LoadDLLFromFile(const char *filename, DL_ResolveMode mode) {
- size_t size;
- char *ptr = _dl_load_file(filename, &size);
- if (!ptr)
- return 0;
-
- DLL *dll = DL_CreateDLL(ptr, size, mode | RTLD_FREE_ON_DESTROY);
- if (!dll)
- free(ptr);
-
- return dll;
-}
-#endif
-
void DL_DestroyDLL(DLL *dll) {
- if (dll == RTLD_DEFAULT)
+ if (!dll)
return;
if (dll->ptr) {
// Call the DLL's global destructors.
const uint32_t *dtor_list = DL_GetDLLSymbol(dll, "__DTOR_LIST__");
if (dtor_list) {
- for (uint32_t i = 0; i < ((uint32_t) dtor_list[0]); i++) {
+ for (int i = 0; i < ((int) dtor_list[0]); i++) {
void (*dtor)(void) = (void (*)(void)) dtor_list[i + 1];
DL_PRE_CALL(dtor);
dtor();
}
}
+
+ dll->ptr = 0;
}
- // If the DLL is associated to a buffer allocated by DL_LoadDLLFromFile(),
- // free that buffer.
- if (dll->malloc_ptr)
+ // If the DLL is associated to a buffer, free that buffer.
+ if (dll->malloc_ptr) {
free(dll->malloc_ptr);
-
- free(dll);
+ dll->malloc_ptr = 0;
+ }
}
void *DL_GetDLLSymbol(const DLL *dll, const char *name) {
- if (dll == RTLD_DEFAULT)
- return DL_GetSymbolByName(name);
- //return _dl_resolve_callback(RTLD_DEFAULT, name);
+ if (!dll)
+ return DL_GetMapSymbol(name);
+ //return _dl_resolve_callback(0, name);
- // https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-48031.html
uint32_t nbucket = dll->hash[0];
uint32_t nchain = dll->hash[1];
const uint32_t *bucket = &(dll->hash[2]);
const uint32_t *chain = &(dll->hash[2 + nbucket]);
- uint32_t hash_mod = _elf_hash(name) % nbucket;
-
// Go through the hash table's chain until the symbol name matches the one
// provided.
- for (uint32_t i = bucket[hash_mod]; i != 0xffffffff;) {
+ for (int i = bucket[_elf_hash(name) % nbucket]; i != 0xffffffff;) {
if (i >= nchain) {
_sdk_log("DL_GetDLLSymbol() index out of bounds (%d >= %d)\n", i, nchain);
- _ERROR(RTLD_E_HASH_LOOKUP, 0);
+ return 0;
}
Elf32_Sym *sym = &(dll->symtab[i]);
@@ -655,12 +525,5 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) {
}
_sdk_log("DLL lookup [%s not found]\n", name);
- _ERROR(RTLD_E_DLL_SYMBOL, 0);
-}
-
-DL_Error DL_GetLastError(void) {
- DL_Error last = _error_code;
- _error_code = RTLD_E_NONE;
-
- return last;
+ return 0;
}