diff options
author | Matt Turner <mattst88@gmail.com> | 2017-11-24 23:09:01 -0800 |
---|---|---|
committer | Matt Turner <mattst88@gmail.com> | 2017-11-24 23:37:07 -0800 |
commit | ca636ca673e3b7ad5132ab1659598f6dffbcd8f7 (patch) | |
tree | 7d307c17317bffe6efd1238ec030a6f2190e9025 | |
parent | dc0cb6998dde6b74c24d991133f774b90e211a92 (diff) |
Add build_id_find_nhdr_by_symbol()
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | build-id.c | 40 | ||||
-rw-r--r-- | build-id.h | 3 |
3 files changed, 44 insertions, 4 deletions
@@ -19,12 +19,13 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +LDLIBS = -ldl LDFLAGS = -Wl,--build-id=sha1 all: build-id so-build-id build-id: test.o build-id.o - $(CC) $(LDFLAGS) $^ -o $@ + $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS) so-build-id: so-test.o libbuild-id.so $(CC) $(LDFLAGS) $^ -o $@ @@ -33,7 +34,7 @@ shared-build-id.o: build-id.c $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -c $^ -o $@ libbuild-id.so: shared-build-id.o - $(CC) $(LDFLAGS) -shared $^ -o $@ + $(CC) $(LDFLAGS) -shared $^ -o $@ $(LDLIBS) clean: rm -f build-id so-build-id libbuild-id.so *.o @@ -23,6 +23,7 @@ */ #define _GNU_SOURCE +#include <dlfcn.h> #include <link.h> #include <stddef.h> #include <string.h> @@ -38,8 +39,16 @@ struct build_id_note { uint8_t build_id[0]; }; +enum tag { BY_NAME, BY_SYMBOL }; + struct callback_data { - const char *name; + union { + const char *name; + + /* Base address of shared object, taken from Dl_info::dli_fbase */ + const void *dli_fbase; + }; + enum tag tag; struct build_id_note *note; }; @@ -48,7 +57,10 @@ build_id_find_nhdr_callback(struct dl_phdr_info *info, size_t size, void *data_) { struct callback_data *data = data_; - if (strcmp(info->dlpi_name, data->name) != 0) + if (data->tag == BY_NAME && strcmp(info->dlpi_name, data->name) != 0) + return 0; + + if (data->tag == BY_SYMBOL && (void *)info->dlpi_addr != data->dli_fbase) return 0; for (unsigned i = 0; i < info->dlpi_phnum; i++) { @@ -83,6 +95,7 @@ const struct build_id_note * build_id_find_nhdr_by_name(const char *name) { struct callback_data data = { + .tag = BY_NAME, .name = name, .note = NULL, }; @@ -93,6 +106,29 @@ build_id_find_nhdr_by_name(const char *name) return data.note; } +const struct build_id_note * +build_id_find_nhdr_by_symbol(const void *symbol) +{ + Dl_info info; + + if (!dladdr(symbol, &info)) + return NULL; + + if (!info.dli_fbase) + return NULL; + + struct callback_data data = { + .tag = BY_SYMBOL, + .dli_fbase = info.dli_fbase, + .note = NULL, + }; + + if (!dl_iterate_phdr(build_id_find_nhdr_callback, &data)) + return NULL; + + return data.note; +} + ElfW(Word) build_id_length(const struct build_id_note *note) { @@ -30,6 +30,9 @@ struct build_id_note; const struct build_id_note * build_id_find_nhdr_by_name(const char *name); +const struct build_id_note * +build_id_find_nhdr_by_symbol(const void *symbol); + ElfW(Word) build_id_length(const struct build_id_note *note); |