#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include <elf.h>
#include <errno.h>
int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum)
{
switch (e_machine) {
case EM_ARM:
return __get_perf_regnum_for_unw_regnum_arm(unw_regnum);
case EM_AARCH64:
return __get_perf_regnum_for_unw_regnum_arm64(unw_regnum);
case EM_LOONGARCH:
return __get_perf_regnum_for_unw_regnum_loongarch(unw_regnum);
case EM_MIPS:
return __get_perf_regnum_for_unw_regnum_mips(unw_regnum);
case EM_PPC:
return __get_perf_regnum_for_unw_regnum_ppc32(unw_regnum);
case EM_PPC64:
return __get_perf_regnum_for_unw_regnum_ppc64(unw_regnum);
case EM_RISCV:
return __get_perf_regnum_for_unw_regnum_riscv(unw_regnum);
case EM_S390:
return __get_perf_regnum_for_unw_regnum_s390(unw_regnum);
case EM_386:
return __get_perf_regnum_for_unw_regnum_i386(unw_regnum);
case EM_X86_64:
return __get_perf_regnum_for_unw_regnum_x86_64(unw_regnum);
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
return -EINVAL;
}
}
void libunwind_arch__flush_access(struct maps *maps)
{
unsigned int e_machine = maps__e_machine(maps);
switch (e_machine) {
case EM_NONE:
break;
case EM_ARM:
__libunwind_arch__flush_access_arm(maps);
break;
case EM_AARCH64:
__libunwind_arch__flush_access_arm64(maps);
break;
case EM_LOONGARCH:
__libunwind_arch__flush_access_loongarch(maps);
break;
case EM_MIPS:
__libunwind_arch__flush_access_mips(maps);
break;
case EM_PPC:
__libunwind_arch__flush_access_ppc32(maps);
break;
case EM_PPC64:
__libunwind_arch__flush_access_ppc64(maps);
break;
case EM_RISCV:
__libunwind_arch__flush_access_riscv(maps);
break;
case EM_S390:
__libunwind_arch__flush_access_s390(maps);
break;
case EM_386:
__libunwind_arch__flush_access_i386(maps);
break;
case EM_X86_64:
__libunwind_arch__flush_access_x86_64(maps);
break;
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
break;
}
}
void libunwind_arch__finish_access(struct maps *maps)
{
unsigned int e_machine = maps__e_machine(maps);
switch (e_machine) {
case EM_NONE:
break;
case EM_ARM:
__libunwind_arch__finish_access_arm(maps);
break;
case EM_AARCH64:
__libunwind_arch__finish_access_arm64(maps);
break;
case EM_LOONGARCH:
__libunwind_arch__finish_access_loongarch(maps);
break;
case EM_MIPS:
__libunwind_arch__finish_access_mips(maps);
break;
case EM_PPC:
__libunwind_arch__finish_access_ppc32(maps);
break;
case EM_PPC64:
__libunwind_arch__finish_access_ppc64(maps);
break;
case EM_RISCV:
__libunwind_arch__finish_access_riscv(maps);
break;
case EM_S390:
__libunwind_arch__finish_access_s390(maps);
break;
case EM_386:
__libunwind_arch__finish_access_i386(maps);
break;
case EM_X86_64:
__libunwind_arch__finish_access_x86_64(maps);
break;
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
break;
}
}
void *libunwind_arch__create_addr_space(unsigned int e_machine)
{
switch (e_machine) {
case EM_ARM:
return __libunwind_arch__create_addr_space_arm();
case EM_AARCH64:
return __libunwind_arch__create_addr_space_arm64();
case EM_LOONGARCH:
return __libunwind_arch__create_addr_space_loongarch();
case EM_MIPS:
return __libunwind_arch__create_addr_space_mips();
case EM_PPC:
return __libunwind_arch__create_addr_space_ppc32();
case EM_PPC64:
return __libunwind_arch__create_addr_space_ppc64();
case EM_RISCV:
return __libunwind_arch__create_addr_space_riscv();
case EM_S390:
return __libunwind_arch__create_addr_space_s390();
case EM_386:
return __libunwind_arch__create_addr_space_i386();
case EM_X86_64:
return __libunwind_arch__create_addr_space_x86_64();
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
return NULL;
}
}
int libunwind_arch__dwarf_search_unwind_table(unsigned int e_machine,
void *as,
uint64_t ip,
struct libarch_unwind__dyn_info *di,
void *pi,
int need_unwind_info,
void *arg)
{
switch (e_machine) {
case EM_ARM:
return __libunwind_arch__dwarf_search_unwind_table_arm(as, ip, di, pi,
need_unwind_info, arg);
case EM_AARCH64:
return __libunwind_arch__dwarf_search_unwind_table_arm64(as, ip, di, pi,
need_unwind_info, arg);
case EM_LOONGARCH:
return __libunwind_arch__dwarf_search_unwind_table_loongarch(as, ip, di, pi,
need_unwind_info, arg);
case EM_MIPS:
return __libunwind_arch__dwarf_search_unwind_table_mips(as, ip, di, pi,
need_unwind_info, arg);
case EM_PPC:
return __libunwind_arch__dwarf_search_unwind_table_ppc32(as, ip, di, pi,
need_unwind_info, arg);
case EM_PPC64:
return __libunwind_arch__dwarf_search_unwind_table_ppc64(as, ip, di, pi,
need_unwind_info, arg);
case EM_RISCV:
return __libunwind_arch__dwarf_search_unwind_table_riscv(as, ip, di, pi,
need_unwind_info, arg);
case EM_S390:
return __libunwind_arch__dwarf_search_unwind_table_s390(as, ip, di, pi,
need_unwind_info, arg);
case EM_386:
return __libunwind_arch__dwarf_search_unwind_table_i386(as, ip, di, pi,
need_unwind_info, arg);
case EM_X86_64:
return __libunwind_arch__dwarf_search_unwind_table_x86_64(as, ip, di, pi,
need_unwind_info, arg);
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
return -EINVAL;
}
}
int libunwind_arch__dwarf_find_debug_frame(unsigned int e_machine,
int found,
struct libarch_unwind__dyn_info *di_debug,
uint64_t ip,
uint64_t segbase,
const char *obj_name,
uint64_t start,
uint64_t end)
{
switch (e_machine) {
case EM_ARM:
return __libunwind_arch__dwarf_find_debug_frame_arm(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_AARCH64:
return __libunwind_arch__dwarf_find_debug_frame_arm64(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_LOONGARCH:
return __libunwind_arch__dwarf_find_debug_frame_loongarch(found, di_debug, ip,
segbase, obj_name,
start, end);
case EM_MIPS:
return __libunwind_arch__dwarf_find_debug_frame_mips(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_PPC:
return __libunwind_arch__dwarf_find_debug_frame_ppc32(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_PPC64:
return __libunwind_arch__dwarf_find_debug_frame_ppc64(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_RISCV:
return __libunwind_arch__dwarf_find_debug_frame_riscv(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_S390:
return __libunwind_arch__dwarf_find_debug_frame_s390(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_386:
return __libunwind_arch__dwarf_find_debug_frame_i386(found, di_debug, ip, segbase,
obj_name, start, end);
case EM_X86_64:
return __libunwind_arch__dwarf_find_debug_frame_x86_64(found, di_debug, ip, segbase,
obj_name, start, end);
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
return -EINVAL;
}
}
struct unwind_info *libunwind_arch_unwind_info__new(struct thread *thread,
struct perf_sample *sample, int max_stack,
bool best_effort, uint16_t e_machine,
uint64_t first_ip)
{
switch (e_machine) {
case EM_ARM:
return __libunwind_arch_unwind_info__new_arm(thread, sample, max_stack,
best_effort, first_ip);
case EM_AARCH64:
return __libunwind_arch_unwind_info__new_arm64(thread, sample, max_stack,
best_effort, first_ip);
case EM_LOONGARCH:
return __libunwind_arch_unwind_info__new_loongarch(thread, sample, max_stack,
best_effort, first_ip);
case EM_MIPS:
return __libunwind_arch_unwind_info__new_mips(thread, sample, max_stack,
best_effort, first_ip);
case EM_PPC:
return __libunwind_arch_unwind_info__new_ppc32(thread, sample, max_stack,
best_effort, first_ip);
case EM_PPC64:
return __libunwind_arch_unwind_info__new_ppc64(thread, sample, max_stack,
best_effort, first_ip);
case EM_RISCV:
return __libunwind_arch_unwind_info__new_riscv(thread, sample, max_stack,
best_effort, first_ip);
case EM_S390:
return __libunwind_arch_unwind_info__new_s390(thread, sample, max_stack,
best_effort, first_ip);
case EM_386:
return __libunwind_arch_unwind_info__new_i386(thread, sample, max_stack,
best_effort, first_ip);
case EM_X86_64:
return __libunwind_arch_unwind_info__new_x86_64(thread, sample, max_stack,
best_effort, first_ip);
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
return NULL;
}
}
void libunwind_arch_unwind_info__delete(struct unwind_info *ui)
{
free(ui);
}
int libunwind_arch__unwind_step(struct unwind_info *ui)
{
switch (ui->e_machine) {
case EM_ARM:
return __libunwind_arch__unwind_step_arm(ui);
case EM_AARCH64:
return __libunwind_arch__unwind_step_arm64(ui);
case EM_LOONGARCH:
return __libunwind_arch__unwind_step_loongarch(ui);
case EM_MIPS:
return __libunwind_arch__unwind_step_mips(ui);
case EM_PPC:
return __libunwind_arch__unwind_step_ppc32(ui);
case EM_PPC64:
return __libunwind_arch__unwind_step_ppc64(ui);
case EM_RISCV:
return __libunwind_arch__unwind_step_riscv(ui);
case EM_S390:
return __libunwind_arch__unwind_step_s390(ui);
case EM_386:
return __libunwind_arch__unwind_step_i386(ui);
case EM_X86_64:
return __libunwind_arch__unwind_step_x86_64(ui);
default:
pr_err("ELF MACHINE %x is not supported.\n", ui->e_machine);
return -EINVAL;
}
}