2 * Copyright © 2016 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #ifdef HAVE_DL_ITERATE_PHDR
33 #ifndef NT_GNU_BUILD_ID
34 #define NT_GNU_BUILD_ID 3
38 #define ElfW(type) Elf_##type
41 struct build_id_note
{
44 char name
[4]; /* Note name for build-id is "GNU\0" */
48 struct callback_data
{
49 /* Base address of shared object, taken from Dl_info::dli_fbase */
50 const void *dli_fbase
;
52 struct build_id_note
*note
;
56 build_id_find_nhdr_callback(struct dl_phdr_info
*info
, size_t size
, void *data_
)
58 struct callback_data
*data
= data_
;
60 /* Calculate address where shared object is mapped into the process space.
61 * (Using the base address and the virtual address of the first LOAD segment)
63 void *map_start
= NULL
;
64 for (unsigned i
= 0; i
< info
->dlpi_phnum
; i
++) {
65 if (info
->dlpi_phdr
[i
].p_type
== PT_LOAD
) {
66 map_start
= (void *)(info
->dlpi_addr
+ info
->dlpi_phdr
[i
].p_vaddr
);
71 if (map_start
!= data
->dli_fbase
)
74 for (unsigned i
= 0; i
< info
->dlpi_phnum
; i
++) {
75 if (info
->dlpi_phdr
[i
].p_type
!= PT_NOTE
)
78 struct build_id_note
*note
= (void *)(info
->dlpi_addr
+
79 info
->dlpi_phdr
[i
].p_vaddr
);
80 ptrdiff_t len
= info
->dlpi_phdr
[i
].p_filesz
;
82 while (len
>= sizeof(struct build_id_note
)) {
83 if (note
->nhdr
.n_type
== NT_GNU_BUILD_ID
&&
84 note
->nhdr
.n_descsz
!= 0 &&
85 note
->nhdr
.n_namesz
== 4 &&
86 memcmp(note
->name
, "GNU", 4) == 0) {
91 size_t offset
= sizeof(ElfW(Nhdr
)) +
92 ALIGN_POT(note
->nhdr
.n_namesz
, 4) +
93 ALIGN_POT(note
->nhdr
.n_descsz
, 4);
94 note
= (struct build_id_note
*)((char *)note
+ offset
);
102 const struct build_id_note
*
103 build_id_find_nhdr_for_addr(const void *addr
)
107 if (!dladdr(addr
, &info
))
113 struct callback_data data
= {
114 .dli_fbase
= info
.dli_fbase
,
118 if (!dl_iterate_phdr(build_id_find_nhdr_callback
, &data
))
125 build_id_length(const struct build_id_note
*note
)
127 return note
->nhdr
.n_descsz
;
131 build_id_data(const struct build_id_note
*note
)
133 return note
->build_id
;