1fdf08e4bSIan Rogers // SPDX-License-Identifier: GPL-2.0 2fdf08e4bSIan Rogers #include "libunwind-arch.h" 3fdf08e4bSIan Rogers #include "../debug.h" 42723e9f8SIan Rogers #include "../maps.h" 5fdf08e4bSIan Rogers #include <elf.h> 6fdf08e4bSIan Rogers #include <errno.h> 7fdf08e4bSIan Rogers 8fdf08e4bSIan Rogers int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum) 9fdf08e4bSIan Rogers { 10fdf08e4bSIan Rogers switch (e_machine) { 11fdf08e4bSIan Rogers case EM_ARM: 12fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_arm(unw_regnum); 13fdf08e4bSIan Rogers case EM_AARCH64: 14fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_arm64(unw_regnum); 15fdf08e4bSIan Rogers case EM_LOONGARCH: 16fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_loongarch(unw_regnum); 17fdf08e4bSIan Rogers case EM_MIPS: 18fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_mips(unw_regnum); 19fdf08e4bSIan Rogers case EM_PPC: 20fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_ppc32(unw_regnum); 21fdf08e4bSIan Rogers case EM_PPC64: 22fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_ppc64(unw_regnum); 23*834c5571SIan Rogers case EM_RISCV: 24*834c5571SIan Rogers return __get_perf_regnum_for_unw_regnum_riscv(unw_regnum); 25fdf08e4bSIan Rogers case EM_S390: 26fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_s390(unw_regnum); 27fdf08e4bSIan Rogers case EM_386: 28fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_i386(unw_regnum); 29fdf08e4bSIan Rogers case EM_X86_64: 30fdf08e4bSIan Rogers return __get_perf_regnum_for_unw_regnum_x86_64(unw_regnum); 31fdf08e4bSIan Rogers default: 32fdf08e4bSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 33fdf08e4bSIan Rogers return -EINVAL; 34fdf08e4bSIan Rogers } 35fdf08e4bSIan Rogers } 362723e9f8SIan Rogers 372723e9f8SIan Rogers 382723e9f8SIan Rogers void libunwind_arch__flush_access(struct maps *maps) 392723e9f8SIan Rogers { 402723e9f8SIan Rogers unsigned int e_machine = maps__e_machine(maps); 412723e9f8SIan Rogers 422723e9f8SIan Rogers switch (e_machine) { 432723e9f8SIan Rogers case EM_NONE: 442723e9f8SIan Rogers break; // No libunwind info on the maps. 452723e9f8SIan Rogers case EM_ARM: 462723e9f8SIan Rogers __libunwind_arch__flush_access_arm(maps); 472723e9f8SIan Rogers break; 482723e9f8SIan Rogers case EM_AARCH64: 492723e9f8SIan Rogers __libunwind_arch__flush_access_arm64(maps); 502723e9f8SIan Rogers break; 512723e9f8SIan Rogers case EM_LOONGARCH: 522723e9f8SIan Rogers __libunwind_arch__flush_access_loongarch(maps); 532723e9f8SIan Rogers break; 542723e9f8SIan Rogers case EM_MIPS: 552723e9f8SIan Rogers __libunwind_arch__flush_access_mips(maps); 562723e9f8SIan Rogers break; 572723e9f8SIan Rogers case EM_PPC: 582723e9f8SIan Rogers __libunwind_arch__flush_access_ppc32(maps); 592723e9f8SIan Rogers break; 602723e9f8SIan Rogers case EM_PPC64: 612723e9f8SIan Rogers __libunwind_arch__flush_access_ppc64(maps); 622723e9f8SIan Rogers break; 63*834c5571SIan Rogers case EM_RISCV: 64*834c5571SIan Rogers __libunwind_arch__flush_access_riscv(maps); 65*834c5571SIan Rogers break; 662723e9f8SIan Rogers case EM_S390: 672723e9f8SIan Rogers __libunwind_arch__flush_access_s390(maps); 682723e9f8SIan Rogers break; 692723e9f8SIan Rogers case EM_386: 702723e9f8SIan Rogers __libunwind_arch__flush_access_i386(maps); 712723e9f8SIan Rogers break; 722723e9f8SIan Rogers case EM_X86_64: 732723e9f8SIan Rogers __libunwind_arch__flush_access_x86_64(maps); 742723e9f8SIan Rogers break; 752723e9f8SIan Rogers default: 762723e9f8SIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 772723e9f8SIan Rogers break; 782723e9f8SIan Rogers } 792723e9f8SIan Rogers } 802723e9f8SIan Rogers 812723e9f8SIan Rogers void libunwind_arch__finish_access(struct maps *maps) 822723e9f8SIan Rogers { 832723e9f8SIan Rogers unsigned int e_machine = maps__e_machine(maps); 842723e9f8SIan Rogers 852723e9f8SIan Rogers switch (e_machine) { 862723e9f8SIan Rogers case EM_NONE: 872723e9f8SIan Rogers break; // No libunwind info on the maps. 882723e9f8SIan Rogers case EM_ARM: 892723e9f8SIan Rogers __libunwind_arch__finish_access_arm(maps); 902723e9f8SIan Rogers break; 912723e9f8SIan Rogers case EM_AARCH64: 922723e9f8SIan Rogers __libunwind_arch__finish_access_arm64(maps); 932723e9f8SIan Rogers break; 942723e9f8SIan Rogers case EM_LOONGARCH: 952723e9f8SIan Rogers __libunwind_arch__finish_access_loongarch(maps); 962723e9f8SIan Rogers break; 972723e9f8SIan Rogers case EM_MIPS: 982723e9f8SIan Rogers __libunwind_arch__finish_access_mips(maps); 992723e9f8SIan Rogers break; 1002723e9f8SIan Rogers case EM_PPC: 1012723e9f8SIan Rogers __libunwind_arch__finish_access_ppc32(maps); 1022723e9f8SIan Rogers break; 1032723e9f8SIan Rogers case EM_PPC64: 1042723e9f8SIan Rogers __libunwind_arch__finish_access_ppc64(maps); 1052723e9f8SIan Rogers break; 106*834c5571SIan Rogers case EM_RISCV: 107*834c5571SIan Rogers __libunwind_arch__finish_access_riscv(maps); 108*834c5571SIan Rogers break; 1092723e9f8SIan Rogers case EM_S390: 1102723e9f8SIan Rogers __libunwind_arch__finish_access_s390(maps); 1112723e9f8SIan Rogers break; 1122723e9f8SIan Rogers case EM_386: 1132723e9f8SIan Rogers __libunwind_arch__finish_access_i386(maps); 1142723e9f8SIan Rogers break; 1152723e9f8SIan Rogers case EM_X86_64: 1162723e9f8SIan Rogers __libunwind_arch__finish_access_x86_64(maps); 1172723e9f8SIan Rogers break; 1182723e9f8SIan Rogers default: 1192723e9f8SIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 1202723e9f8SIan Rogers break; 1212723e9f8SIan Rogers } 1222723e9f8SIan Rogers } 12388b4275fSIan Rogers 12488b4275fSIan Rogers void *libunwind_arch__create_addr_space(unsigned int e_machine) 12588b4275fSIan Rogers { 12688b4275fSIan Rogers switch (e_machine) { 12788b4275fSIan Rogers case EM_ARM: 12888b4275fSIan Rogers return __libunwind_arch__create_addr_space_arm(); 12988b4275fSIan Rogers case EM_AARCH64: 13088b4275fSIan Rogers return __libunwind_arch__create_addr_space_arm64(); 13188b4275fSIan Rogers case EM_LOONGARCH: 13288b4275fSIan Rogers return __libunwind_arch__create_addr_space_loongarch(); 13388b4275fSIan Rogers case EM_MIPS: 13488b4275fSIan Rogers return __libunwind_arch__create_addr_space_mips(); 13588b4275fSIan Rogers case EM_PPC: 13688b4275fSIan Rogers return __libunwind_arch__create_addr_space_ppc32(); 13788b4275fSIan Rogers case EM_PPC64: 13888b4275fSIan Rogers return __libunwind_arch__create_addr_space_ppc64(); 139*834c5571SIan Rogers case EM_RISCV: 140*834c5571SIan Rogers return __libunwind_arch__create_addr_space_riscv(); 14188b4275fSIan Rogers case EM_S390: 14288b4275fSIan Rogers return __libunwind_arch__create_addr_space_s390(); 14388b4275fSIan Rogers case EM_386: 14488b4275fSIan Rogers return __libunwind_arch__create_addr_space_i386(); 14588b4275fSIan Rogers case EM_X86_64: 14688b4275fSIan Rogers return __libunwind_arch__create_addr_space_x86_64(); 14788b4275fSIan Rogers default: 14888b4275fSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 14988b4275fSIan Rogers return NULL; 15088b4275fSIan Rogers } 15188b4275fSIan Rogers } 15288b4275fSIan Rogers 15388b4275fSIan Rogers int libunwind_arch__dwarf_search_unwind_table(unsigned int e_machine, 15488b4275fSIan Rogers void *as, 15588b4275fSIan Rogers uint64_t ip, 15688b4275fSIan Rogers struct libarch_unwind__dyn_info *di, 15788b4275fSIan Rogers void *pi, 15888b4275fSIan Rogers int need_unwind_info, 15988b4275fSIan Rogers void *arg) 16088b4275fSIan Rogers { 16188b4275fSIan Rogers switch (e_machine) { 16288b4275fSIan Rogers case EM_ARM: 16388b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_arm(as, ip, di, pi, 16488b4275fSIan Rogers need_unwind_info, arg); 16588b4275fSIan Rogers case EM_AARCH64: 16688b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_arm64(as, ip, di, pi, 16788b4275fSIan Rogers need_unwind_info, arg); 16888b4275fSIan Rogers case EM_LOONGARCH: 16988b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_loongarch(as, ip, di, pi, 17088b4275fSIan Rogers need_unwind_info, arg); 17188b4275fSIan Rogers case EM_MIPS: 17288b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_mips(as, ip, di, pi, 17388b4275fSIan Rogers need_unwind_info, arg); 17488b4275fSIan Rogers case EM_PPC: 17588b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_ppc32(as, ip, di, pi, 17688b4275fSIan Rogers need_unwind_info, arg); 17788b4275fSIan Rogers case EM_PPC64: 17888b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_ppc64(as, ip, di, pi, 17988b4275fSIan Rogers need_unwind_info, arg); 180*834c5571SIan Rogers case EM_RISCV: 181*834c5571SIan Rogers return __libunwind_arch__dwarf_search_unwind_table_riscv(as, ip, di, pi, 182*834c5571SIan Rogers need_unwind_info, arg); 18388b4275fSIan Rogers case EM_S390: 18488b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_s390(as, ip, di, pi, 18588b4275fSIan Rogers need_unwind_info, arg); 18688b4275fSIan Rogers case EM_386: 18788b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_i386(as, ip, di, pi, 18888b4275fSIan Rogers need_unwind_info, arg); 18988b4275fSIan Rogers case EM_X86_64: 19088b4275fSIan Rogers return __libunwind_arch__dwarf_search_unwind_table_x86_64(as, ip, di, pi, 19188b4275fSIan Rogers need_unwind_info, arg); 19288b4275fSIan Rogers default: 19388b4275fSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 19488b4275fSIan Rogers return -EINVAL; 19588b4275fSIan Rogers } 19688b4275fSIan Rogers } 19788b4275fSIan Rogers 19888b4275fSIan Rogers int libunwind_arch__dwarf_find_debug_frame(unsigned int e_machine, 19988b4275fSIan Rogers int found, 20088b4275fSIan Rogers struct libarch_unwind__dyn_info *di_debug, 20188b4275fSIan Rogers uint64_t ip, 20288b4275fSIan Rogers uint64_t segbase, 20388b4275fSIan Rogers const char *obj_name, 20488b4275fSIan Rogers uint64_t start, 20588b4275fSIan Rogers uint64_t end) 20688b4275fSIan Rogers { 20788b4275fSIan Rogers switch (e_machine) { 20888b4275fSIan Rogers case EM_ARM: 20988b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_arm(found, di_debug, ip, segbase, 21088b4275fSIan Rogers obj_name, start, end); 21188b4275fSIan Rogers case EM_AARCH64: 21288b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_arm64(found, di_debug, ip, segbase, 21388b4275fSIan Rogers obj_name, start, end); 21488b4275fSIan Rogers case EM_LOONGARCH: 21588b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_loongarch(found, di_debug, ip, 21688b4275fSIan Rogers segbase, obj_name, 21788b4275fSIan Rogers start, end); 21888b4275fSIan Rogers case EM_MIPS: 21988b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_mips(found, di_debug, ip, segbase, 22088b4275fSIan Rogers obj_name, start, end); 22188b4275fSIan Rogers case EM_PPC: 22288b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_ppc32(found, di_debug, ip, segbase, 22388b4275fSIan Rogers obj_name, start, end); 22488b4275fSIan Rogers case EM_PPC64: 22588b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_ppc64(found, di_debug, ip, segbase, 22688b4275fSIan Rogers obj_name, start, end); 227*834c5571SIan Rogers case EM_RISCV: 228*834c5571SIan Rogers return __libunwind_arch__dwarf_find_debug_frame_riscv(found, di_debug, ip, segbase, 229*834c5571SIan Rogers obj_name, start, end); 23088b4275fSIan Rogers case EM_S390: 23188b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_s390(found, di_debug, ip, segbase, 23288b4275fSIan Rogers obj_name, start, end); 23388b4275fSIan Rogers case EM_386: 23488b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_i386(found, di_debug, ip, segbase, 23588b4275fSIan Rogers obj_name, start, end); 23688b4275fSIan Rogers case EM_X86_64: 23788b4275fSIan Rogers return __libunwind_arch__dwarf_find_debug_frame_x86_64(found, di_debug, ip, segbase, 23888b4275fSIan Rogers obj_name, start, end); 23988b4275fSIan Rogers default: 24088b4275fSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 24188b4275fSIan Rogers return -EINVAL; 24288b4275fSIan Rogers } 24388b4275fSIan Rogers } 24488b4275fSIan Rogers 24588b4275fSIan Rogers struct unwind_info *libunwind_arch_unwind_info__new(struct thread *thread, 24688b4275fSIan Rogers struct perf_sample *sample, int max_stack, 24788b4275fSIan Rogers bool best_effort, uint16_t e_machine, 24888b4275fSIan Rogers uint64_t first_ip) 24988b4275fSIan Rogers { 25088b4275fSIan Rogers switch (e_machine) { 25188b4275fSIan Rogers case EM_ARM: 25288b4275fSIan Rogers return __libunwind_arch_unwind_info__new_arm(thread, sample, max_stack, 25388b4275fSIan Rogers best_effort, first_ip); 25488b4275fSIan Rogers case EM_AARCH64: 25588b4275fSIan Rogers return __libunwind_arch_unwind_info__new_arm64(thread, sample, max_stack, 25688b4275fSIan Rogers best_effort, first_ip); 25788b4275fSIan Rogers case EM_LOONGARCH: 25888b4275fSIan Rogers return __libunwind_arch_unwind_info__new_loongarch(thread, sample, max_stack, 25988b4275fSIan Rogers best_effort, first_ip); 26088b4275fSIan Rogers case EM_MIPS: 26188b4275fSIan Rogers return __libunwind_arch_unwind_info__new_mips(thread, sample, max_stack, 26288b4275fSIan Rogers best_effort, first_ip); 26388b4275fSIan Rogers case EM_PPC: 26488b4275fSIan Rogers return __libunwind_arch_unwind_info__new_ppc32(thread, sample, max_stack, 26588b4275fSIan Rogers best_effort, first_ip); 26688b4275fSIan Rogers case EM_PPC64: 26788b4275fSIan Rogers return __libunwind_arch_unwind_info__new_ppc64(thread, sample, max_stack, 26888b4275fSIan Rogers best_effort, first_ip); 269*834c5571SIan Rogers case EM_RISCV: 270*834c5571SIan Rogers return __libunwind_arch_unwind_info__new_riscv(thread, sample, max_stack, 271*834c5571SIan Rogers best_effort, first_ip); 27288b4275fSIan Rogers case EM_S390: 27388b4275fSIan Rogers return __libunwind_arch_unwind_info__new_s390(thread, sample, max_stack, 27488b4275fSIan Rogers best_effort, first_ip); 27588b4275fSIan Rogers case EM_386: 27688b4275fSIan Rogers return __libunwind_arch_unwind_info__new_i386(thread, sample, max_stack, 27788b4275fSIan Rogers best_effort, first_ip); 27888b4275fSIan Rogers case EM_X86_64: 27988b4275fSIan Rogers return __libunwind_arch_unwind_info__new_x86_64(thread, sample, max_stack, 28088b4275fSIan Rogers best_effort, first_ip); 28188b4275fSIan Rogers default: 28288b4275fSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", e_machine); 28388b4275fSIan Rogers return NULL; 28488b4275fSIan Rogers } 28588b4275fSIan Rogers } 28688b4275fSIan Rogers 28788b4275fSIan Rogers void libunwind_arch_unwind_info__delete(struct unwind_info *ui) 28888b4275fSIan Rogers { 28988b4275fSIan Rogers free(ui); 29088b4275fSIan Rogers } 29188b4275fSIan Rogers 29288b4275fSIan Rogers int libunwind_arch__unwind_step(struct unwind_info *ui) 29388b4275fSIan Rogers { 29488b4275fSIan Rogers switch (ui->e_machine) { 29588b4275fSIan Rogers case EM_ARM: 29688b4275fSIan Rogers return __libunwind_arch__unwind_step_arm(ui); 29788b4275fSIan Rogers case EM_AARCH64: 29888b4275fSIan Rogers return __libunwind_arch__unwind_step_arm64(ui); 29988b4275fSIan Rogers case EM_LOONGARCH: 30088b4275fSIan Rogers return __libunwind_arch__unwind_step_loongarch(ui); 30188b4275fSIan Rogers case EM_MIPS: 30288b4275fSIan Rogers return __libunwind_arch__unwind_step_mips(ui); 30388b4275fSIan Rogers case EM_PPC: 30488b4275fSIan Rogers return __libunwind_arch__unwind_step_ppc32(ui); 30588b4275fSIan Rogers case EM_PPC64: 30688b4275fSIan Rogers return __libunwind_arch__unwind_step_ppc64(ui); 307*834c5571SIan Rogers case EM_RISCV: 308*834c5571SIan Rogers return __libunwind_arch__unwind_step_riscv(ui); 30988b4275fSIan Rogers case EM_S390: 31088b4275fSIan Rogers return __libunwind_arch__unwind_step_s390(ui); 31188b4275fSIan Rogers case EM_386: 31288b4275fSIan Rogers return __libunwind_arch__unwind_step_i386(ui); 31388b4275fSIan Rogers case EM_X86_64: 31488b4275fSIan Rogers return __libunwind_arch__unwind_step_x86_64(ui); 31588b4275fSIan Rogers default: 31688b4275fSIan Rogers pr_err("ELF MACHINE %x is not supported.\n", ui->e_machine); 31788b4275fSIan Rogers return -EINVAL; 31888b4275fSIan Rogers } 31988b4275fSIan Rogers } 320