xref: /aosp_15_r20/external/mesa3d/src/util/build_id.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #ifdef HAVE_DL_ITERATE_PHDR
25*61046927SAndroid Build Coastguard Worker #include <dlfcn.h>
26*61046927SAndroid Build Coastguard Worker #include <link.h>
27*61046927SAndroid Build Coastguard Worker #include <stddef.h>
28*61046927SAndroid Build Coastguard Worker #include <string.h>
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "build_id.h"
31*61046927SAndroid Build Coastguard Worker #include "macros.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #ifndef NT_GNU_BUILD_ID
34*61046927SAndroid Build Coastguard Worker #define NT_GNU_BUILD_ID 3
35*61046927SAndroid Build Coastguard Worker #endif
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker #ifndef ElfW
38*61046927SAndroid Build Coastguard Worker #define ElfW(type) Elf_##type
39*61046927SAndroid Build Coastguard Worker #endif
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker struct build_id_note {
42*61046927SAndroid Build Coastguard Worker    ElfW(Nhdr) nhdr;
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker    char name[4]; /* Note name for build-id is "GNU\0" */
45*61046927SAndroid Build Coastguard Worker    uint8_t build_id[0];
46*61046927SAndroid Build Coastguard Worker };
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker struct callback_data {
49*61046927SAndroid Build Coastguard Worker    /* Base address of shared object, taken from Dl_info::dli_fbase */
50*61046927SAndroid Build Coastguard Worker    const void *dli_fbase;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    struct build_id_note *note;
53*61046927SAndroid Build Coastguard Worker };
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker static int
build_id_find_nhdr_callback(struct dl_phdr_info * info,size_t size,void * data_)56*61046927SAndroid Build Coastguard Worker build_id_find_nhdr_callback(struct dl_phdr_info *info, size_t size, void *data_)
57*61046927SAndroid Build Coastguard Worker {
58*61046927SAndroid Build Coastguard Worker    struct callback_data *data = data_;
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker    /* Calculate address where shared object is mapped into the process space.
61*61046927SAndroid Build Coastguard Worker     * (Using the base address and the virtual address of the first LOAD segment)
62*61046927SAndroid Build Coastguard Worker     */
63*61046927SAndroid Build Coastguard Worker    void *map_start = NULL;
64*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < info->dlpi_phnum; i++) {
65*61046927SAndroid Build Coastguard Worker       if (info->dlpi_phdr[i].p_type == PT_LOAD) {
66*61046927SAndroid Build Coastguard Worker          map_start = (void *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
67*61046927SAndroid Build Coastguard Worker          break;
68*61046927SAndroid Build Coastguard Worker       }
69*61046927SAndroid Build Coastguard Worker    }
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    if (map_start != data->dli_fbase)
72*61046927SAndroid Build Coastguard Worker       return 0;
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < info->dlpi_phnum; i++) {
75*61046927SAndroid Build Coastguard Worker       if (info->dlpi_phdr[i].p_type != PT_NOTE)
76*61046927SAndroid Build Coastguard Worker          continue;
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker       struct build_id_note *note = (void *)(info->dlpi_addr +
79*61046927SAndroid Build Coastguard Worker                                             info->dlpi_phdr[i].p_vaddr);
80*61046927SAndroid Build Coastguard Worker       ptrdiff_t len = info->dlpi_phdr[i].p_filesz;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker       while (len >= sizeof(struct build_id_note)) {
83*61046927SAndroid Build Coastguard Worker          if (note->nhdr.n_type == NT_GNU_BUILD_ID &&
84*61046927SAndroid Build Coastguard Worker             note->nhdr.n_descsz != 0 &&
85*61046927SAndroid Build Coastguard Worker             note->nhdr.n_namesz == 4 &&
86*61046927SAndroid Build Coastguard Worker             memcmp(note->name, "GNU", 4) == 0) {
87*61046927SAndroid Build Coastguard Worker             data->note = note;
88*61046927SAndroid Build Coastguard Worker             return 1;
89*61046927SAndroid Build Coastguard Worker          }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker          size_t offset = sizeof(ElfW(Nhdr)) +
92*61046927SAndroid Build Coastguard Worker                          ALIGN_POT(note->nhdr.n_namesz, 4) +
93*61046927SAndroid Build Coastguard Worker                          ALIGN_POT(note->nhdr.n_descsz, 4);
94*61046927SAndroid Build Coastguard Worker          note = (struct build_id_note *)((char *)note + offset);
95*61046927SAndroid Build Coastguard Worker          len -= offset;
96*61046927SAndroid Build Coastguard Worker       }
97*61046927SAndroid Build Coastguard Worker    }
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    return 0;
100*61046927SAndroid Build Coastguard Worker }
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker const struct build_id_note *
build_id_find_nhdr_for_addr(const void * addr)103*61046927SAndroid Build Coastguard Worker build_id_find_nhdr_for_addr(const void *addr)
104*61046927SAndroid Build Coastguard Worker {
105*61046927SAndroid Build Coastguard Worker    Dl_info info;
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    if (!dladdr(addr, &info))
108*61046927SAndroid Build Coastguard Worker       return NULL;
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    if (!info.dli_fbase)
111*61046927SAndroid Build Coastguard Worker       return NULL;
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    struct callback_data data = {
114*61046927SAndroid Build Coastguard Worker       .dli_fbase = info.dli_fbase,
115*61046927SAndroid Build Coastguard Worker       .note = NULL,
116*61046927SAndroid Build Coastguard Worker    };
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker    if (!dl_iterate_phdr(build_id_find_nhdr_callback, &data))
119*61046927SAndroid Build Coastguard Worker       return NULL;
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker    return data.note;
122*61046927SAndroid Build Coastguard Worker }
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker unsigned
build_id_length(const struct build_id_note * note)125*61046927SAndroid Build Coastguard Worker build_id_length(const struct build_id_note *note)
126*61046927SAndroid Build Coastguard Worker {
127*61046927SAndroid Build Coastguard Worker    return note->nhdr.n_descsz;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker const uint8_t *
build_id_data(const struct build_id_note * note)131*61046927SAndroid Build Coastguard Worker build_id_data(const struct build_id_note *note)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker    return note->build_id;
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker #endif
137