On 13/10/2019 09.18, Bill Wendling wrote: > Two global objects can't have the same address in C. Clang uses this > fact to omit the check on the first iteration of the loop in > check_exception_table. > > Signed-off-by: Bill Wendling <morbo@xxxxxxxxxx> > --- > lib/x86/desc.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/lib/x86/desc.c b/lib/x86/desc.c > index 451f504..cfc449f 100644 > --- a/lib/x86/desc.c > +++ b/lib/x86/desc.c > @@ -41,7 +41,7 @@ struct ex_record { > unsigned long handler; > }; > > -extern struct ex_record exception_table_start, exception_table_end; > +extern struct ex_record exception_table_start, *exception_table_end; > > static const char* exception_mnemonic(int vector) > { > @@ -113,7 +113,7 @@ static void check_exception_table(struct ex_regs *regs) > (((regs->rflags >> 16) & 1) << 8); > asm("mov %0, %%gs:4" : : "r"(ex_val)); > > - for (ex = &exception_table_start; ex != &exception_table_end; ++ex) { > + for (ex = &exception_table_start; ex != (void*)&exception_table_end; ++ex) { > if (ex->rip == regs->rip) { > regs->rip = ex->handler; > return; > That looks like quite an ugly hack to me - and if clang gets a little bit smarter, I'm pretty sure it will optimize this away, too. Could you please check if something like this works, too: diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 451f504..0e9779b 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -41,7 +41,8 @@ struct ex_record { unsigned long handler; }; -extern struct ex_record exception_table_start, exception_table_end; +extern struct ex_record exception_table_start; +extern long exception_table_size; static const char* exception_mnemonic(int vector) { @@ -108,12 +109,13 @@ static void check_exception_table(struct ex_regs *regs) { struct ex_record *ex; unsigned ex_val; + int cnt = exception_table_size / sizeof(struct ex_record); ex_val = regs->vector | (regs->error_code << 16) | (((regs->rflags >> 16) & 1) << 8); asm("mov %0, %%gs:4" : : "r"(ex_val)); - for (ex = &exception_table_start; ex != &exception_table_end; ++ex) { + for (ex = &exception_table_start; cnt-- > 0; ++ex) { if (ex->rip == regs->rip) { regs->rip = ex->handler; return; diff --git a/x86/flat.lds b/x86/flat.lds index a278b56..108fad5 100644 --- a/x86/flat.lds +++ b/x86/flat.lds @@ -9,6 +9,7 @@ SECTIONS exception_table_start = .; *(.data.ex) exception_table_end = .; + exception_table_size = exception_table_end - exception_table_start; } . = ALIGN(16); .rodata : { *(.rodata) } Thomas