On 02/16/2011 01:44 PM, Paul Koning wrote:
I'm running into a crash caused by mishandling of address calculation of an
array element address when that array is near the bottom of kseg0
(0xffffffff80000000).
The code essentially does this
foo = v[i - 2].elem;
where i is current zero.
Assume for now the negative array offset is valid -- data structure elements in question
exist to both sides of the label "v".
The generated code looks like this:
/* i is in v0 */
addiu v0, -2
sll v0, 3
lui v1, 0x8000
addu v0, v1
lbu a1, 7110(v0)
What's going on here is that&v[0].elem is 0xfffffffff80007110. The reference
is valid -- array elements are 8 bytes so element -2 is still in kseg0.
However, the addu produces value 0000000007ffffff0 in v0 -- the result of
adding -16 to the 32 bit value 0x800000000.
Given that I have an ABI with 64 bit registers -- even though it has 32 bit
pointers -- I would say the address adjustment should have been done with
daddu; if that had been done I would have gotten the correct address.
GCC is 4.5.1, NetBSD target.
This is why it is a bad idea to place anything in the 2^16 byte region
centered on the split.
The Linux kernel works around this by not using the lower 32kb of
ckseg0. It also never user the top 32kb of useg when in 32bit mode.
David Daney.