From: Szabolcs Nagy <nsz@port70.net>
To: musl@lists.openwall.com
Subject: Re: armv7-m segv when throwing c++ exception
Date: Wed, 2 Oct 2019 11:22:33 +0200 [thread overview]
Message-ID: <20191002092233.GB7832@port70.net> (raw)
In-Reply-To: <CAEg67GmE0zz5gpVn_uS6ufG2LTODfipiDxE3XWvNh4QbuQAwww@mail.gmail.com>
* Patrick Oppenlander <patrick.oppenlander@gmail.com> [2019-10-02 12:00:19 +1000]:
> Hi all,
>
> I'm running into an issue with a gcc-8.3.0/musl-1.1.23 toolchain built
> using musl-cross-make for armv7-m.
>
> % cat test.cpp
> int main()
> {
> throw 0;
> }
> % armv7m-linux-musleabihf-g++ -ggdb -static test.cpp
> % qemu-arm ./a.out
> qemu: uncaught target signal 11 (Segmentation fault) - core dumped
> [2] 198246 segmentation fault (core dumped) qemu-arm ./a.out
>
> We should be seeing something like "terminate called after throwing an
> instance of 'int'".
there is at least one known issue in this area:
libgcc uses pthread apis via weak refs so with static
linking they don't get linked in, however i think that
should only affect unwinding in multi-thread processes,
so this is something else
> I have an ODROID-C2 here which is a convenient place to run gdb:
>
> $ gdb -q ./a.out
> Reading symbols from ./a.out...
> (gdb) run
> Program received signal SIGSEGV, Segmentation fault.
> 0xf77cf9f4 in __cxxabiv1::__cxa_throw (obj=0xf77f5fa0,
> tinfo=0xf77efb20 <typeinfo for int>, dest=0x0)
> at ../../../../src_gcc/libstdc++-v3/libsupc++/eh_throw.cc:81
> 81 ../../../../src_gcc/libstdc++-v3/libsupc++/eh_throw.cc: No such
> file or directory.
> (gdb) bt
> #0 0xf77cf9f4 in __cxxabiv1::__cxa_throw (obj=0xf77f5fa0,
> tinfo=0xf77efb20 <typeinfo for int>, dest=0x0)
> at ../../../../src_gcc/libstdc++-v3/libsupc++/eh_throw.cc:81
> #1 0xf77cf902 in main () at test.cpp:3
> (gdb) disas
> Dump of assembler code for function __cxxabiv1::__cxa_throw(void*,
> std::type_info*, void (*)(void*)):
> 0xf77cf9e0 <+0>: push {r3, r4, r5, r6, r7, lr}
> 0xf77cf9e2 <+2>: mov r5, r0
> 0xf77cf9e4 <+4>: mov r7, r1
> 0xf77cf9e6 <+6>: mov r6, r2
> 0xf77cf9e8 <+8>: bl 0xf77d01c4 <__cxxabiv1::__cxa_get_globals()>
> 0xf77cf9ec <+12>: mov r4, r0
> 0xf77cf9ee <+14>: mov r1, r7
> 0xf77cf9f0 <+16>: mov r2, r6
> 0xf77cf9f2 <+18>: mov r0, r5
> => 0xf77cf9f4 <+20>: ldr r3, [r4, #4]
> 0xf77cf9f6 <+22>: adds r3, #1
> 0xf77cf9f8 <+24>: str r3, [r4, #4]
> 0xf77cf9fa <+26>: bl 0xf77cf984
> <__cxxabiv1::__cxa_init_primary_exception(void*, std::type_info*, void
> (*)(void*))>
> 0xf77cf9fe <+30>: movs r3, #1
> 0xf77cfa00 <+32>: mov r4, r0
> 0xf77cfa02 <+34>: str.w r3, [r4], #40
> 0xf77cfa06 <+38>: mov r0, r4
> 0xf77cfa08 <+40>: bl 0xf77d88a8 <___Unwind_RaiseException>
> 0xf77cfa0c <+44>: mov r0, r4
> 0xf77cfa0e <+46>: bl 0xf77d01e0 <__cxxabiv1::__cxa_begin_catch(void*)>
> 0xf77cfa12 <+50>: bl 0xf77cfaf0 <std::terminate()>
> End of assembler dump.
> (gdb) p/x $r4
> $1 = 0x1
>
> That doesn't look good.
>
> (gdb) disas __cxa_get_globals
> Dump of assembler code for function __cxxabiv1::__cxa_get_globals():
> 0xf77d01c4 <+0>: ldr r0, [pc, #12] ; (0xf77d01d4
> <__cxxabiv1::__cxa_get_globals()+16>)
> 0xf77d01c6 <+2>: push {r3, lr}
> 0xf77d01c8 <+4>: add r0, pc
> 0xf77d01ca <+6>: bl 0xf77da940 <__tls_get_addr>
> 0xf77d01ce <+10>: ldr r3, [pc, #8] ; (0xf77d01d8
> <__cxxabiv1::__cxa_get_globals()+20>)
> 0xf77d01d0 <+12>: add r0, r3
> 0xf77d01d2 <+14>: pop {r3, pc}
> 0xf77d01d4 <+16>: ; <UNDEFINED> instruction: 0001fe40
> 0xf77d01d8 <+20>: ; <UNDEFINED> instruction: 00000000
> End of assembler dump.
interesting, i thought the linker would relax __tls_get_addr
calls in static linked executables to local-exec access model,
but maybe that's not implemented on arm.
can you look at the readelf -aW a.out and see if the linker
left any dynamic tls relocs in the exe?
>
> OK, so what did __tls_get_addr return?
>
> (gdb) b *(__cxa_get_globals + 10)
> Breakpoint 3 at 0xf77d01ce: file
> ../../../../src_gcc/libstdc++-v3/libsupc++/eh_globals.cc, line 62.
> (gdb) run
> Breakpoint 3, 0xf77d01ce in __cxxabiv1::__cxa_get_globals () at
> ../../../../src_gcc/libstdc++-v3/libsupc++/eh_globals.cc:62
> 62 ../../../../src_gcc/libstdc++-v3/libsupc++/eh_globals.cc: No such
> file or directory.
> (gdb) p/x $r0
> $3 = 0x1
>
> That's doesn't look good either. Let's look at __tls_get_addr.
>
> void *__tls_get_addr(tls_mod_off_t *v)
> {
> pthread_t self = __pthread_self();
> return (void *)(self->dtv[v[0]] + v[1]);
> }
>
> (gdb) disas __tls_get_addr (annotations added by me)
> Dump of assembler code for function __tls_get_addr:
> r2 = v[0]
> 0x0000c940 <+0>: ldr r2, [r0, #0]
> r3 = tls
> 0x0000c942 <+2>: ; <UNDEFINED> instruction: 0xee1d3f70
> self = r3 - 120
> r3 = *(r3 - 116) = self->dtv
> 0x0000c946 <+6>: ldr.w r3, [r3, #-116]
> r0 = v[1]
> 0x0000c94a <+10>: ldr r0, [r0, #4]
> r2 = *(r3 + r2 * 4) = dtv[r2]
> 0x0000c94c <+12>: ldr.w r2, [r3, r2, lsl #2]
> r0 = r0 + r2
> 0x0000c950 <+16>: add r0, r2
> 0x0000c952 <+18>: bx lr
> End of assembler dump.
> (gdb) b __tls_get_addr
>
> So after pulling out the values I end up with:
> v = 0xf77f000c
> 0xf77f000c: 0x00000000 0x00000000 0xf77f072c 0xf77eff1c
> v[0] = 0
> v[1] = 0
> self = <builtin_tls> 0xf77f064c
> 0xf77f064c <builtin_tls>: 0xf77f064c 0xf77f06dc 0xf77f064c 0xf77f064c
> self->dtv = <builtin_tls+144> 0xf77f06dc
> 0xf77f06dc <builtin_tls+144>: 0x00000001 0xf77f06cc 0x00000000 0x00000000
> return = dtv[v[0]] + v[1] = 1 + 0 = 1
>
> At this point I'm out of my depth.
dtv[0] is special and just stores the length of the dtv
(which is correctly 1, meaning there is 1 elf module with tls).
so the issue is that v[0]==0 instead of 1 (dtv[1] would hold
the tls address of the executable) i think v[0] should be set
up by the static linker so it may be a binutils bug.
(or maybe static linking is special and then dtv[0] should be
set equal to dtv[1]?)
>
> Where should I look next?
>
> Thanks,
>
> Patrick
next prev parent reply other threads:[~2019-10-02 9:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-02 2:00 Patrick Oppenlander
2019-10-02 9:22 ` Szabolcs Nagy [this message]
2019-10-02 11:40 ` Rich Felker
2019-10-02 11:49 ` Rich Felker
2019-10-02 12:25 ` Rich Felker
2019-10-02 12:49 ` Rich Felker
2019-10-02 14:55 ` Rich Felker
2019-10-02 22:34 ` Patrick Oppenlander
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191002092233.GB7832@port70.net \
--to=nsz@port70.net \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).