From ca636ca673e3b7ad5132ab1659598f6dffbcd8f7 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Fri, 24 Nov 2017 23:09:01 -0800 Subject: Add build_id_find_nhdr_by_symbol() --- Makefile | 5 +++-- build-id.c | 40 ++++++++++++++++++++++++++++++++++++++-- build-id.h | 3 +++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5c4295f..a1a7207 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/build-id.c b/build-id.c index 96bbf3e..bd6faae 100644 --- a/build-id.c +++ b/build-id.c @@ -23,6 +23,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -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) { diff --git a/build-id.h b/build-id.h index 8505d9b..e3e64cf 100644 --- a/build-id.h +++ b/build-id.h @@ -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); -- cgit v1.2.3