xref: /aosp_15_r20/trusty/kernel/lib/backtrace/symbolize.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2020 Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker #include <lib/backtrace/symbolize.h>
25*344aa361SAndroid Build Coastguard Worker #include <trace.h>
26*344aa361SAndroid Build Coastguard Worker 
27*344aa361SAndroid Build Coastguard Worker #include "elf_sym.h"
28*344aa361SAndroid Build Coastguard Worker 
29*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE 0
30*344aa361SAndroid Build Coastguard Worker 
31*344aa361SAndroid Build Coastguard Worker #undef ELF_64BIT
32*344aa361SAndroid Build Coastguard Worker #if !IS_64BIT || USER_32BIT
33*344aa361SAndroid Build Coastguard Worker #define ELF_64BIT 0
34*344aa361SAndroid Build Coastguard Worker #else
35*344aa361SAndroid Build Coastguard Worker #define ELF_64BIT 1
36*344aa361SAndroid Build Coastguard Worker #endif
37*344aa361SAndroid Build Coastguard Worker 
38*344aa361SAndroid Build Coastguard Worker #if ELF_64BIT
39*344aa361SAndroid Build Coastguard Worker #define ELF_SHDR Elf64_Shdr
40*344aa361SAndroid Build Coastguard Worker #define ELF_EHDR Elf64_Ehdr
41*344aa361SAndroid Build Coastguard Worker #define ELF_SYM Elf64_Sym
42*344aa361SAndroid Build Coastguard Worker #else
43*344aa361SAndroid Build Coastguard Worker #define ELF_SHDR Elf32_Shdr
44*344aa361SAndroid Build Coastguard Worker #define ELF_EHDR Elf32_Ehdr
45*344aa361SAndroid Build Coastguard Worker #define ELF_SYM Elf32_Sym
46*344aa361SAndroid Build Coastguard Worker #endif
47*344aa361SAndroid Build Coastguard Worker 
range_within_app_img(uintptr_t start,size_t size,struct trusty_app_img * app_img)48*344aa361SAndroid Build Coastguard Worker static inline bool range_within_app_img(uintptr_t start,
49*344aa361SAndroid Build Coastguard Worker                                         size_t size,
50*344aa361SAndroid Build Coastguard Worker                                         struct trusty_app_img* app_img) {
51*344aa361SAndroid Build Coastguard Worker     uintptr_t end;
52*344aa361SAndroid Build Coastguard Worker     if (__builtin_add_overflow(start, size, &end)) {
53*344aa361SAndroid Build Coastguard Worker         return false;
54*344aa361SAndroid Build Coastguard Worker     }
55*344aa361SAndroid Build Coastguard Worker     return app_img->img_start <= start && end <= app_img->img_end;
56*344aa361SAndroid Build Coastguard Worker }
57*344aa361SAndroid Build Coastguard Worker 
range_within_range(uintptr_t start0,size_t size0,uintptr_t start1,size_t size1)58*344aa361SAndroid Build Coastguard Worker static inline bool range_within_range(uintptr_t start0,
59*344aa361SAndroid Build Coastguard Worker                                       size_t size0,
60*344aa361SAndroid Build Coastguard Worker                                       uintptr_t start1,
61*344aa361SAndroid Build Coastguard Worker                                       size_t size1) {
62*344aa361SAndroid Build Coastguard Worker     uintptr_t end0;
63*344aa361SAndroid Build Coastguard Worker     if (__builtin_add_overflow(start0, size0, &end0)) {
64*344aa361SAndroid Build Coastguard Worker         return false;
65*344aa361SAndroid Build Coastguard Worker     }
66*344aa361SAndroid Build Coastguard Worker     uintptr_t end1;
67*344aa361SAndroid Build Coastguard Worker     if (__builtin_add_overflow(start1, size1, &end1)) {
68*344aa361SAndroid Build Coastguard Worker         return false;
69*344aa361SAndroid Build Coastguard Worker     }
70*344aa361SAndroid Build Coastguard Worker     return start1 <= start0 && end0 <= end1;
71*344aa361SAndroid Build Coastguard Worker }
72*344aa361SAndroid Build Coastguard Worker 
trusty_app_symbolize(struct trusty_app * app,uintptr_t pc,struct pc_symbol_info * info)73*344aa361SAndroid Build Coastguard Worker int trusty_app_symbolize(struct trusty_app* app,
74*344aa361SAndroid Build Coastguard Worker                          uintptr_t pc,
75*344aa361SAndroid Build Coastguard Worker                          struct pc_symbol_info* info) {
76*344aa361SAndroid Build Coastguard Worker     if (!app) {
77*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
78*344aa361SAndroid Build Coastguard Worker     }
79*344aa361SAndroid Build Coastguard Worker     /* Adjust pc to be relative to app image */
80*344aa361SAndroid Build Coastguard Worker     if (__builtin_sub_overflow(pc, app->load_bias, &pc)) {
81*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
82*344aa361SAndroid Build Coastguard Worker     }
83*344aa361SAndroid Build Coastguard Worker     /* pc must be within the app image */
84*344aa361SAndroid Build Coastguard Worker     struct trusty_app_img* app_img = &app->app_img;
85*344aa361SAndroid Build Coastguard Worker     if (app_img->img_end <= app_img->img_start) {
86*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
87*344aa361SAndroid Build Coastguard Worker     }
88*344aa361SAndroid Build Coastguard Worker     if (pc > app_img->img_end - app_img->img_start) {
89*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
90*344aa361SAndroid Build Coastguard Worker     }
91*344aa361SAndroid Build Coastguard Worker 
92*344aa361SAndroid Build Coastguard Worker     ELF_EHDR* ehdr = (ELF_EHDR*)app_img->img_start;
93*344aa361SAndroid Build Coastguard Worker     ELF_SHDR* shdr = (ELF_SHDR*)((uintptr_t)ehdr + ehdr->e_shoff);
94*344aa361SAndroid Build Coastguard Worker 
95*344aa361SAndroid Build Coastguard Worker     ELF_SHDR* symtab_shdr = NULL;
96*344aa361SAndroid Build Coastguard Worker     ELF_SHDR* strtab_shdr = NULL;
97*344aa361SAndroid Build Coastguard Worker 
98*344aa361SAndroid Build Coastguard Worker     /* Find section headers for .symtab and .strtab */
99*344aa361SAndroid Build Coastguard Worker     for (size_t i = 0; i < ehdr->e_shnum; i++) {
100*344aa361SAndroid Build Coastguard Worker         if (shdr[i].sh_type == SHT_SYMTAB) {
101*344aa361SAndroid Build Coastguard Worker             symtab_shdr = shdr + i;
102*344aa361SAndroid Build Coastguard Worker         }
103*344aa361SAndroid Build Coastguard Worker         if (shdr[i].sh_type == SHT_STRTAB) {
104*344aa361SAndroid Build Coastguard Worker             strtab_shdr = shdr + i;
105*344aa361SAndroid Build Coastguard Worker         }
106*344aa361SAndroid Build Coastguard Worker     }
107*344aa361SAndroid Build Coastguard Worker 
108*344aa361SAndroid Build Coastguard Worker     /* Handle the case when app is not built with .symtab or .strtab */
109*344aa361SAndroid Build Coastguard Worker     if (!symtab_shdr || !strtab_shdr) {
110*344aa361SAndroid Build Coastguard Worker         LTRACEF("App built without symbol table\n");
111*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
112*344aa361SAndroid Build Coastguard Worker     }
113*344aa361SAndroid Build Coastguard Worker 
114*344aa361SAndroid Build Coastguard Worker     uintptr_t symtab_start = app_img->img_start + symtab_shdr->sh_offset;
115*344aa361SAndroid Build Coastguard Worker     size_t symtab_size = symtab_shdr->sh_size;
116*344aa361SAndroid Build Coastguard Worker     uintptr_t strtab_start = app_img->img_start + strtab_shdr->sh_offset;
117*344aa361SAndroid Build Coastguard Worker     size_t strtab_size = strtab_shdr->sh_size;
118*344aa361SAndroid Build Coastguard Worker 
119*344aa361SAndroid Build Coastguard Worker     /* Validate .symtab and .strtab locations */
120*344aa361SAndroid Build Coastguard Worker     if (!range_within_app_img(symtab_start, symtab_size, app_img)) {
121*344aa361SAndroid Build Coastguard Worker         TRACEF(".symtab section is not within the app image\n");
122*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
123*344aa361SAndroid Build Coastguard Worker     }
124*344aa361SAndroid Build Coastguard Worker     if (!range_within_app_img(strtab_start, strtab_size, app_img)) {
125*344aa361SAndroid Build Coastguard Worker         TRACEF(".strtab section is not within the app image\n");
126*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
127*344aa361SAndroid Build Coastguard Worker     }
128*344aa361SAndroid Build Coastguard Worker 
129*344aa361SAndroid Build Coastguard Worker     /* Find closest symbol preceding pc */
130*344aa361SAndroid Build Coastguard Worker     info->offset = ULONG_MAX;
131*344aa361SAndroid Build Coastguard Worker     for (uintptr_t curr = symtab_start;
132*344aa361SAndroid Build Coastguard Worker          curr < symtab_start + symtab_shdr->sh_size;
133*344aa361SAndroid Build Coastguard Worker          curr += symtab_shdr->sh_entsize) {
134*344aa361SAndroid Build Coastguard Worker         /* Entry must be within .symtab section */
135*344aa361SAndroid Build Coastguard Worker         if (!range_within_range(curr, symtab_shdr->sh_entsize, symtab_start,
136*344aa361SAndroid Build Coastguard Worker                                 symtab_size)) {
137*344aa361SAndroid Build Coastguard Worker             TRACEF(".symtab section is malformed\n");
138*344aa361SAndroid Build Coastguard Worker             goto out_no_symbol;
139*344aa361SAndroid Build Coastguard Worker         }
140*344aa361SAndroid Build Coastguard Worker 
141*344aa361SAndroid Build Coastguard Worker         ELF_SYM* symtab_entry = (ELF_SYM*)curr;
142*344aa361SAndroid Build Coastguard Worker         /* We are looking for a symbol of a function */
143*344aa361SAndroid Build Coastguard Worker         if (ELF_ST_TYPE(symtab_entry->st_info) != STT_FUNC) {
144*344aa361SAndroid Build Coastguard Worker             continue;
145*344aa361SAndroid Build Coastguard Worker         }
146*344aa361SAndroid Build Coastguard Worker 
147*344aa361SAndroid Build Coastguard Worker         uintptr_t func_start = symtab_entry->st_value;
148*344aa361SAndroid Build Coastguard Worker         if (func_start <= pc && info->offset > pc - func_start) {
149*344aa361SAndroid Build Coastguard Worker             /* Offset must be within .strtab section */
150*344aa361SAndroid Build Coastguard Worker             if (symtab_entry->st_name >= strtab_size) {
151*344aa361SAndroid Build Coastguard Worker                 TRACEF(".strtab section is malformed\n");
152*344aa361SAndroid Build Coastguard Worker                 goto out_no_symbol;
153*344aa361SAndroid Build Coastguard Worker             }
154*344aa361SAndroid Build Coastguard Worker 
155*344aa361SAndroid Build Coastguard Worker             info->symbol = (const char*)(strtab_start + symtab_entry->st_name);
156*344aa361SAndroid Build Coastguard Worker             info->offset = pc - func_start;
157*344aa361SAndroid Build Coastguard Worker             info->size = symtab_entry->st_size;
158*344aa361SAndroid Build Coastguard Worker         }
159*344aa361SAndroid Build Coastguard Worker     }
160*344aa361SAndroid Build Coastguard Worker 
161*344aa361SAndroid Build Coastguard Worker     if (info->offset == ULONG_MAX) {
162*344aa361SAndroid Build Coastguard Worker         goto out_no_symbol;
163*344aa361SAndroid Build Coastguard Worker     }
164*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
165*344aa361SAndroid Build Coastguard Worker 
166*344aa361SAndroid Build Coastguard Worker out_no_symbol:
167*344aa361SAndroid Build Coastguard Worker     info->symbol = NULL;
168*344aa361SAndroid Build Coastguard Worker     info->offset = 0;
169*344aa361SAndroid Build Coastguard Worker     info->size = 0;
170*344aa361SAndroid Build Coastguard Worker     return ERR_NOT_FOUND;
171*344aa361SAndroid Build Coastguard Worker }
172