interesting linker behaviour :)
willy found a problem this morning with the exception code which was traced down to the following:
the following code comes from lusercopy.S (with macros expanded):
lstrncpy_from_user:
.proc
.callinfo NO_CALLS
.entry
comib,= 0,%r24,$lsfu_done
copy %r24,%r23
get_sr
1: ldbs,ma 1(%sr1,%r25),%r1
$lsfu_loop:
stbs,ma %r1,1(%r26)
comib,=,n 0,%r1,$lsfu_done
addib,<>,n -1,%r24,$lsfu_loop
2: ldbs,ma 1(%sr1,%r25),%r1
$lsfu_done:
sub %r23,%r24,%r28
$lsfu_exit:
bv %r0(%r2)
nop
.exit
.section .fixup,"ax"
3: b $lsfu_exit
ldi -EFAULT,%r28
.previous
.section __ex_table,"aw"
.word 1b,3b
.word 2b,3b
.previous
.procendwhat is supposed to happen is that when a fault happens at "1:", we would branch to "3:". The code in "3:" sets the return value to -EFAULT and branches back to the exit path.
what we observed was that when a fault happens, we get an endless loop of faults.
when i disassembled the code at 3:, i see:
1038ce68: e8 05 00 7d b,l 10357eac <tcpdiag_dump+0x5ac>,r0 1038ce6c: 34 1c 3f e5 ldi -e,ret0
the target of the branch is a long branch stub:
10357eac: 20 20 02 02 ldil 10100000,r1 10357eb0: e0 20 22 b2 be,n 158(sr4,r1)
but 10100158 is lstrncpy_from_user, not $lsfu_exit:
10100158 <lstrncpy_from_user>
10100190 <$lsfu_exit>
i wonder if the sections are somehow confusing things.... this is with fairly recent gcc/binutils toolchains, for 32-bit.
randolph
Signature · 7 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 6 lines · Randolph Chung
but 10100158 is
lstrncpy_from_user, not $lsfu_exit:
10100158 <lstrncpy_from_user>
10100190 <$lsfu_exit>i wonder if the sections are somehow confusing things.... this is with fairly recent gcc/binutils toolchains, for 32-bit.
Multiple entry points to a function may not work if an import stub is required? The import stubs are thrown into a hash, and it probably thinks it's okay for you to use the same import stub. You on the other want a second entry point.
I recommend you give the exit it's own symbol, .export and .import the linker thinks it's two different functions?
c.
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 8 lines · Carlos O'Donell
Quoted 6 lines · Randolph Chung
but 10100158 is
lstrncpy_from_user, not $lsfu_exit:
10100158 <lstrncpy_from_user>
10100190 <$lsfu_exit>i wonder if the sections are somehow confusing things.... this is with fairly recent gcc/binutils toolchains, for 32-bit.
Quoted 7 lines
Multiple entry points to a function may not work if an import stub is required? The import stubs are thrown into a hash, and it probably thinks it's okay for you to use the same import stub. You on the other want a second entry point.
I recommend you give the exit it's own symbol, .export and .import the linker thinks it's two different functions?
Wow. I need to stop and re-read my emails.
a. Multiple entry points to a function, and import stubs probably don't
mix well.
b. Define a symbol for lsfu_exit, .export it, then .import it later
and branch to that symbol. We want the linker to think it's two different functions.
I think that is clearer? :)
c.
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 8 lines · Randolph Chung
Quoted 6 lines
but 10100158 is
lstrncpy_from_user, not $lsfu_exit:
10100158 <lstrncpy_from_user>
10100190 <$lsfu_exit>i wonder if the sections are somehow confusing things.... this is with fairly recent gcc/binutils toolchains, for 32-bit.
Quoted 7 lines
Multiple entry points to a function may not work if an import stub is required? The import stubs are thrown into a hash, and it probably thinks it's okay for you to use the same import stub. You on the other want a second entry point.
I recommend you give the exit it's own symbol, .export and .import the linker thinks it's two different functions?
Good catch! I've hit this problem before but under HP-UX. GAS doesn't support the alternate entry point fixup needed to support multiple entry points to a function. I don't think anyone has tried to support this with the ELF tools. There could be some nasty interactions with the HP unwind data when you start adding multiple entry points to a function.
I haven't looked at this in detail but possibly you can change the fixup table to contain pc-relative offsets. I looked at this when I reworked the casesi pattern in GCC a few months ago. This makes the table smaller and in many cases the number of instructions is less than that with branches in the table (particularly for the PIC case). I ended up putting the table in the same section as the text since in that case the offsets were absolute. However, I did look at putting the offsets in readonly data. This is where I came up with the method to create 32 and 64-bit pc-relative offsets. It takes a couple of extra instructions to load the address of a table that's in a different section. As a side, I believe that only 32-bit offsets are needed in the 64-bit runtime.
Dave
Signature · 6 lines
J. David Anglin [email protected] National Research Council of Canada (613) 990-0752 (FAX: 952-6602) _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 6 lines
Good catch! I've hit this problem before but under HP-UX. GAS doesn't support the alternate entry point fixup needed to support multiple entry points to a function. I don't think anyone has tried to support this with the ELF tools. There could be some nasty interactions with the HP unwind data when you start adding multiple entry points to a function.
yeah, it will break unwinding :(
Quoted 6 lines
I haven't looked at this in detail but possibly you can change the fixup table to contain pc-relative offsets. I looked at this when I reworked the casesi pattern in GCC a few months ago. This makes the table smaller and in many cases the number of instructions is less than that with branches in the table (particularly for the PIC case).
well, this is what we used to do, but we don't do this now because it requires us to be able to do a pc-relative calculation between code in two different sections (text and fixup), and GAS doesn't allow that either.
for now i'm using the solution we are using for 64-bit code, which is to use a manually created long-branch stub (ldil/ldo/bv). since this is anyway in a slow-path the performance hit is probably negligible.
randolph
Signature · 7 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 11 lines
Quoted 6 lines
I haven't looked at this in detail but possibly you can change the fixup table to contain pc-relative offsets. I looked at this when I reworked the casesi pattern in GCC a few months ago. This makes the table smaller and in many cases the number of instructions is less than that with branches in the table (particularly for the PIC case).
well, this is what we used to do, but we don't do this now because it requires us to be able to do a pc-relative calculation between code in two different sections (text and fixup), and GAS doesn't allow that either.
GAS does allow you to do it. If you look in GCC, you will see that we use the special assembler symbol $PIC_pcrel$0 to create pc-relative relocations. To create a jump table with 32-bit pc-relative relocations, you would do something like this:
L$0:
.word L$1+(.+8-L$0)-$PIC_pcrel$0 .word L$2+(.+8-L$0)-$PIC_pcrel$0 ...
The assembler is sensitive to the ordering of the terms in the expression.
Basically, $PIC_pcrel$0 == .+8 in each expression, so you are just left with the difference of labels in the final evaluation. Note that (.+8-L$0) evaluates to an absolute constant. Thus, the first two terms are just a symbol plus a constant addend. GAS will allow that.
Dave
Signature · 6 lines
J. David Anglin [email protected] National Research Council of Canada (613) 990-0752 (FAX: 952-6602) _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 3 lines
for now i'm using the solution we are using for 64-bit code, which is to use a manually created long-branch stub (ldil/ldo/bv). since this is anyway in a slow-path the performance hit is probably negligible.
As I suggested before, you can shorten (ldil/ldo/bv) to (ldil/be) if if you know which space register to use in the be (in user space, %sr4 will always work since the address space is flat).
The linker doesn't insert stubs for the (ldil/be) sequence although possibly it should.
The code sequence to handle 32-bit pc-relative offsets is going to be longer than either of the above two sequences. So, possibly you would only want to go this route if the table is large.
Dave
Signature · 6 lines
J. David Anglin [email protected] National Research Council of Canada (613) 990-0752 (FAX: 952-6602) _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 3 lines
As I suggested before, you can shorten (ldil/ldo/bv) to (ldil/be) if if you know which space register to use in the be (in user space, %sr4 will always work since the address space is flat).
erm, yes, you did say that, and i forgot. i will change it.
randolph
Signature · 7 lines
Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 16 lines · John David Anglin
Quoted 8 lines · Randolph Chung
Quoted 6 lines
but 10100158 is
lstrncpy_from_user, not $lsfu_exit:
10100158 <lstrncpy_from_user>
10100190 <$lsfu_exit>i wonder if the sections are somehow confusing things.... this is with fairly recent gcc/binutils toolchains, for 32-bit.
Quoted 7 lines
Multiple entry points to a function may not work if an import stub is required? The import stubs are thrown into a hash, and it probably thinks it's okay for you to use the same import stub. You on the other want a second entry point.
I recommend you give the exit it's own symbol, .export and .import the linker thinks it's two different functions?
Quoted 6 lines
Good catch! I've hit this problem before but under HP-UX. GAS doesn't support the alternate entry point fixup needed to support multiple entry points to a function. I don't think anyone has tried to support this with the ELF tools. There could be some nasty interactions with the HP unwind data when you start adding multiple entry points to a function.
I think you said we had similar problems with non-local goto's?
Either we had a conversation about multiple entry points, or I read it in one of the HP documents :)
c.
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 4 lines · Carlos O'Donell
I think you said we had similar problems with non-local goto's?
Either we had a conversation about multiple entry points, or I read it in one of the HP documents :)
Randolph,
See! If we had a wiki it would be under 'john david anglin says' :)
c.
_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
Quoted 8 lines
Quoted 6 lines
Good catch! I've hit this problem before but under HP-UX. GAS doesn't support the alternate entry point fixup needed to support multiple entry points to a function. I don't think anyone has tried to support this with the ELF tools. There could be some nasty interactions with the HP unwind data when you start adding multiple entry points to a function.
I think you said we had similar problems with non-local goto's?
Right, that's where it came up. As of 6/11/04, we have a new nonlocal_goto expander. I'm a little foggy on this issue but I think prior to the tree-ssa merge the default nonlocal_goto expander was ok.
Dave
Signature · 6 lines
J. David Anglin [email protected] National Research Council of Canada (613) 990-0752 (FAX: 952-6602) _______________________________________________ parisc-linux mailing list [email protected] http://lists.parisc-linux.org/mailman/listinfo/parisc-linux