mirror of
https://github.com/opnsense/src.git
synced 2026-02-21 17:00:58 -05:00
Update the unwind information when modules are loaded and unloaded
by using the linker hooks. Since these hooks are called for the
kernel as well, we don't need to deal with that with a special
SYSINIT. The initialization implicitly performed on the first
update of the unwind information is made explicit with a SYSINIT.
We now don't need the _ia64_unwind_{start|end} symbols.
This commit is contained in:
parent
1aeb23cdfa
commit
c8a4afbc11
4 changed files with 85 additions and 52 deletions
|
|
@ -218,15 +218,44 @@ elf_reloc(linker_file_t lf, const void *data, int type)
|
|||
}
|
||||
|
||||
int
|
||||
elf_cpu_load_file(linker_file_t lf __unused)
|
||||
elf_cpu_load_file(linker_file_t lf)
|
||||
{
|
||||
Elf_Ehdr *hdr;
|
||||
Elf_Phdr *ph, *phlim;
|
||||
Elf_Addr reloc, vaddr;
|
||||
|
||||
hdr = (Elf_Ehdr *)(lf->address);
|
||||
if (!IS_ELF(*hdr)) {
|
||||
printf("Missing or corrupted ELF header at %p\n", hdr);
|
||||
return (EFTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the segments and register the unwind table if
|
||||
* we come across it.
|
||||
*/
|
||||
ph = (Elf_Phdr *)(lf->address + hdr->e_phoff);
|
||||
phlim = ph + hdr->e_phnum;
|
||||
reloc = ~0ULL;
|
||||
while (ph < phlim) {
|
||||
if (ph->p_type == PT_LOAD && reloc == ~0ULL)
|
||||
reloc = (Elf_Addr)lf->address - ph->p_vaddr;
|
||||
|
||||
if (ph->p_type == PT_IA_64_UNWIND) {
|
||||
vaddr = ph->p_vaddr + reloc;
|
||||
ia64_add_unwind_table((vm_offset_t)lf->address, vaddr,
|
||||
vaddr + ph->p_memsz);
|
||||
}
|
||||
++ph;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
elf_cpu_unload_file(linker_file_t lf)
|
||||
{
|
||||
|
||||
ia64_delete_unwind_table((vm_offset_t)lf->address);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,8 +109,6 @@ struct user *proc0uarea;
|
|||
vm_offset_t proc0kstack;
|
||||
|
||||
extern u_int64_t kernel_text[], _end[];
|
||||
extern u_int64_t _ia64_unwind_start[];
|
||||
extern u_int64_t _ia64_unwind_end[];
|
||||
|
||||
FPSWA_INTERFACE *fpswa_interface;
|
||||
|
||||
|
|
@ -303,18 +301,6 @@ identifycpu(void)
|
|||
"\001LB");
|
||||
}
|
||||
|
||||
static void
|
||||
add_kernel_unwind_tables(void *arg)
|
||||
{
|
||||
/*
|
||||
* Register the kernel's unwind table.
|
||||
*/
|
||||
ia64_add_unwind_table(kernel_text,
|
||||
_ia64_unwind_start,
|
||||
_ia64_unwind_end);
|
||||
}
|
||||
SYSINIT(unwind, SI_SUB_KMEM, SI_ORDER_ANY, add_kernel_unwind_tables, 0);
|
||||
|
||||
void
|
||||
map_pal_code(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,42 +122,23 @@ static struct ia64_unwind_table_list ia64_unwind_tables;
|
|||
static struct ia64_unwind_state ia64_unwind_state_static[MAX_UNWIND_STATES];
|
||||
static LIST_HEAD(ia64_unwind_state_list, ia64_unwind_state) ia64_unwind_states;
|
||||
|
||||
struct ia64_unwind_table *
|
||||
ia64_add_unwind_table(u_int64_t *base, u_int64_t *start, u_int64_t *end)
|
||||
static void
|
||||
ia64_initialise_unwind(void *arg __unused)
|
||||
{
|
||||
struct ia64_unwind_table *ut;
|
||||
int i;
|
||||
|
||||
if (!ia64_unwind_initialised) {
|
||||
int i;
|
||||
LIST_INIT(&ia64_unwind_tables);
|
||||
LIST_INIT(&ia64_unwind_states);
|
||||
for (i = 0; i < MAX_UNWIND_STATES; i++) {
|
||||
LIST_INSERT_HEAD(&ia64_unwind_states,
|
||||
&ia64_unwind_state_static[i],
|
||||
us_link);
|
||||
}
|
||||
ia64_unwind_initialised = 1;
|
||||
KASSERT(!ia64_unwind_initialised, ("foo"));
|
||||
|
||||
LIST_INIT(&ia64_unwind_tables);
|
||||
LIST_INIT(&ia64_unwind_states);
|
||||
for (i = 0; i < MAX_UNWIND_STATES; i++) {
|
||||
LIST_INSERT_HEAD(&ia64_unwind_states,
|
||||
&ia64_unwind_state_static[i], us_link);
|
||||
}
|
||||
|
||||
ut = malloc(sizeof(struct ia64_unwind_table), M_UNWIND, M_NOWAIT);
|
||||
if (!ut)
|
||||
return 0;
|
||||
|
||||
ut->ut_base = (u_int64_t) base;
|
||||
ut->ut_start = (struct ia64_unwind_table_entry *) start;
|
||||
ut->ut_end = (struct ia64_unwind_table_entry *) end;
|
||||
ut->ut_limit = (u_int64_t) base + ut->ut_end[-1].ue_end;
|
||||
LIST_INSERT_HEAD(&ia64_unwind_tables, ut, ut_link);
|
||||
|
||||
return ut;
|
||||
}
|
||||
|
||||
void
|
||||
ia64_free_unwind_table(struct ia64_unwind_table *ut)
|
||||
{
|
||||
LIST_REMOVE(ut, ut_link);
|
||||
free(ut, M_UNWIND);
|
||||
ia64_unwind_initialised = 1;
|
||||
}
|
||||
SYSINIT(unwind, SI_SUB_KMEM, SI_ORDER_ANY, ia64_initialise_unwind, 0);
|
||||
|
||||
static struct ia64_unwind_table *
|
||||
find_table(u_int64_t ip)
|
||||
|
|
@ -198,6 +179,46 @@ find_entry(struct ia64_unwind_table *ut, u_int64_t ip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ia64_add_unwind_table(vm_offset_t base, vm_offset_t start, vm_offset_t end)
|
||||
{
|
||||
struct ia64_unwind_table *ut;
|
||||
|
||||
KASSERT(ia64_unwind_initialised, ("foo"));
|
||||
|
||||
ut = malloc(sizeof(struct ia64_unwind_table), M_UNWIND, M_NOWAIT);
|
||||
if (ut == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
ut->ut_base = base;
|
||||
ut->ut_start = (struct ia64_unwind_table_entry*)start;
|
||||
ut->ut_end = (struct ia64_unwind_table_entry*)end;
|
||||
ut->ut_limit = base + ut->ut_end[-1].ue_end;
|
||||
LIST_INSERT_HEAD(&ia64_unwind_tables, ut, ut_link);
|
||||
|
||||
if (bootverbose)
|
||||
printf("UNWIND: table added: base=%lx, start=%lx, end=%lx\n",
|
||||
base, start, end);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ia64_delete_unwind_table(vm_offset_t base)
|
||||
{
|
||||
struct ia64_unwind_table *ut;
|
||||
|
||||
KASSERT(ia64_unwind_initialised, ("foo"));
|
||||
|
||||
ut = find_table(base);
|
||||
if (ut != NULL) {
|
||||
LIST_REMOVE(ut, ut_link);
|
||||
free(ut, M_UNWIND);
|
||||
if (bootverbose)
|
||||
printf("UNWIND: table removed: base=%lx\n", base);
|
||||
}
|
||||
}
|
||||
|
||||
struct ia64_unwind_state *
|
||||
ia64_create_unwind_state(struct trapframe *framep)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,12 +26,9 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
struct ia64_unwind_table;
|
||||
int ia64_add_unwind_table(vm_offset_t, vm_offset_t, vm_offset_t);
|
||||
void ia64_delete_unwind_table(vm_offset_t);
|
||||
|
||||
struct ia64_unwind_table *ia64_add_unwind_table(u_int64_t *base,
|
||||
u_int64_t *start,
|
||||
u_int64_t *end);
|
||||
void ia64_free_unwind_table(struct ia64_unwind_table *ut);
|
||||
struct ia64_unwind_state *ia64_create_unwind_state(struct trapframe *framep);
|
||||
void ia64_free_unwind_state(struct ia64_unwind_state *us);
|
||||
u_int64_t ia64_unwind_state_get_ip(struct ia64_unwind_state *us);
|
||||
|
|
|
|||
Loading…
Reference in a new issue