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
31 #ifndef NT_GNU_BUILD_ID
32 #define NT_GNU_BUILD_ID 3
36 #define ElfW(type) Elf_##type
39 #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
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 if ((void *)info
->dlpi_addr
!= data
->dli_fbase
)
63 for (unsigned i
= 0; i
< info
->dlpi_phnum
; i
++) {
64 if (info
->dlpi_phdr
[i
].p_type
!= PT_NOTE
)
67 struct build_id_note
*note
= (void *)(info
->dlpi_addr
+
68 info
->dlpi_phdr
[i
].p_vaddr
);
69 ptrdiff_t len
= info
->dlpi_phdr
[i
].p_filesz
;
71 while (len
>= sizeof(struct build_id_note
)) {
72 if (note
->nhdr
.n_type
== NT_GNU_BUILD_ID
&&
73 note
->nhdr
.n_descsz
!= 0 &&
74 note
->nhdr
.n_namesz
== 4 &&
75 memcmp(note
->name
, "GNU", 4) == 0) {
80 size_t offset
= sizeof(ElfW(Nhdr
)) +
81 ALIGN(note
->nhdr
.n_namesz
, 4) +
82 ALIGN(note
->nhdr
.n_descsz
, 4);
83 note
= (struct build_id_note
*)((char *)note
+ offset
);
91 const struct build_id_note
*
92 build_id_find_nhdr_for_addr(const void *addr
)
96 if (!dladdr(addr
, &info
))
102 struct callback_data data
= {
103 .dli_fbase
= info
.dli_fbase
,
107 if (!dl_iterate_phdr(build_id_find_nhdr_callback
, &data
))
114 build_id_length(const struct build_id_note
*note
)
116 return note
->nhdr
.n_descsz
;
120 build_id_data(const struct build_id_note
*note
)
122 return note
->build_id
;