summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2017-11-24 23:09:01 -0800
committerMatt Turner <mattst88@gmail.com>2017-11-24 23:37:07 -0800
commitca636ca673e3b7ad5132ab1659598f6dffbcd8f7 (patch)
tree7d307c17317bffe6efd1238ec030a6f2190e9025
parentdc0cb6998dde6b74c24d991133f774b90e211a92 (diff)
Add build_id_find_nhdr_by_symbol()
-rw-r--r--Makefile5
-rw-r--r--build-id.c40
-rw-r--r--build-id.h3
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 <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)
{
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);