[coreboot] libpayload alloc() gcc 4.6.2 bug?
Marc Jones
marcj303 at gmail.com
Tue Feb 28 23:06:30 CET 2012
I think I found a bug in gcc 4.6.2 building libpayload (current
coreboot crosstools). I would like to get confirmation that someone
else sees this and that I haven't done something wrong. Please let me
know if there is anything else I should try or post. I'm not sure how
to address this. Comments welcome.
I found this bug building tint with libpayload. libpayload is built
with defconfig and using the same coreboot crosstools gcc. The bug
happens in the first call to alloc() when the first header of the
first region is installed. The header memory location is checked,
found to be 0, and then loaded with the header. The bug is that the
original value of the location is used after the memory was updated.
It should have been reloaded. It is pretty easy to see in the
disassembly below.
The libpayload alloc function:
static void *alloc(int len)
{
hdrtype_t header;
void *ptr = hstart;
/* Align the size. */
len = (len + 3) & ~3;
if (!len || len > 0xffffff)
return (void *)NULL;
/* Make sure the region is setup correctly. */
if (!HAS_MAGIC(*((hdrtype_t *) ptr)))
setup();
/* Find some free space. */
do {
header = *((hdrtype_t *) ptr);
int size = SIZE(header);
if (!HAS_MAGIC(header) || size == 0) { <---- fails
here due to *((hdrtype_t *) ptr) not being refreshed after memory
changes
printf("memory allocator panic. (%s%s)\n",
!HAS_MAGIC(header) ? " no magic " : "",
size == 0 ? " size=0 " : "");
The failing asm:
0010b7c0 <alloc>:
10b7c0: 56 push %esi
10b7c1: 53 push %ebx
10b7c2: 83 ec 14 sub $0x14,%esp
10b7c5: 8d 70 03 lea 0x3(%eax),%esi
10b7c8: 83 e6 fc and $0xfffffffc,%esi
10b7cb: 74 7c je 10b849 <alloc+0x89>
10b7cd: 81 fe ff ff ff 00 cmp $0xffffff,%esi
10b7d3: 7f 74 jg 10b849 <alloc+0x89>
10b7d5: a1 a0 5f 11 00 mov 0x115fa0,%eax <---
load alloc header into eax
10b7da: 89 c2 mov %eax,%edx <---
moves it to edx
10b7dc: 81 e2 00 00 00 a8 and $0xa8000000,%edx
10b7e2: 81 fa 00 00 00 a8 cmp $0xa8000000,%edx
10b7e8: 74 1d je 10b807 <alloc+0x47>
10b7ea: ba 9c 9f 11 00 mov $0x119f9c,%edx <--- setup()
10b7ef: 81 ea a0 5f 11 00 sub $0x115fa0,%edx
10b7f5: 81 e2 ff ff ff 00 and $0xffffff,%edx
10b7fb: 81 ca 00 00 00 aa or $0xaa000000,%edx
10b801: 89 15 a0 5f 11 00 mov %edx,0x115fa0 <--- memory write
10b807: ba a0 5f 11 00 mov $0x115fa0,%edx
10b80c: eb 04 jmp 10b812 <alloc+0x52>
10b80e: 66 90 xchg %ax,%ax
10b810: 8b 02 mov (%edx),%eax
10b812: 89 c1 mov %eax,%ecx <----
starts using eax, but the memory was changed and not reloaded
10b814: 81 e1 ff ff ff 00 and $0xffffff,%ecx
This is a passing version built with the old toolchain (gcc 4.5.2):
0010b24c <alloc>:
10b24c: 55 push %ebp
10b24d: 89 e5 mov %esp,%ebp
10b24f: 56 push %esi
10b250: 53 push %ebx
10b251: 83 c0 03 add $0x3,%eax
10b254: 83 e0 fc and $0xfffffffc,%eax
10b257: 75 0b jne 10b264 <alloc+0x18>
10b259: 31 c0 xor %eax,%eax
10b25b: 8d 65 f8 lea -0x8(%ebp),%esp
10b25e: 5b pop %ebx
10b25f: 5e pop %esi
10b260: c9 leave
10b261: c3 ret
10b262: 66 90 xchg %ax,%ax
10b264: 3d ff ff ff 00 cmp $0xffffff,%eax
10b269: 7f ee jg 10b259 <alloc+0xd>
10b26b: 8b 15 00 14 11 00 mov 0x111400,%edx
<--- loads alloc header into edx.
10b271: 89 d1 mov %edx,%ecx
10b273: 81 e1 00 00 00 a8 and $0xa8000000,%ecx
10b279: 81 f9 00 00 00 a8 cmp $0xa8000000,%ecx
10b27f: 74 1f je 10b2a0 <alloc+0x54>
10b281: ba 00 14 11 00 mov $0x111400,%edx <--- setup()
10b286: f7 da neg %edx
10b288: 81 c2 fc 53 11 00 add $0x1153fc,%edx
10b28e: 81 e2 ff ff ff 00 and $0xffffff,%edx
10b294: 81 ca 00 00 00 aa or $0xaa000000,%edx
10b29a: 89 15 00 14 11 00 mov %edx,0x111400 <---
memory updated and still in edx
10b2a0: b9 00 14 11 00 mov $0x111400,%ecx
10b2a5: eb 03 jmp 10b2aa <alloc+0x5e>
10b2a7: 90 nop
10b2a8: 8b 11 mov (%ecx),%edx
10b2aa: 89 d3 mov %edx,%ebx <---
edx has correct value
My failing gcc version:
$ /i386-elf-gcc -v
Using built-in specs.
COLLECT_GCC=/home/marc/git/coreboot2/payloads/tint-0.03b/./../../util/crossgcc/xgcc/bin/i386-elf-gcc
COLLECT_LTO_WRAPPER=/home/marc/devel/coreboot/util/crossgcc/xgcc/lib/gcc/i386-elf/4.6.2/lto-wrapper
Target: i386-elf
Configured with: ../gcc-4.6.2/configure --enable-multilib=yes
--prefix=/home/marc/devel/coreboot/util/crossgcc/xgcc
--libexecdir=/home/marc/devel/coreboot/util/crossgcc/xgcc/lib
--target=i386-elf --disable-werror --disable-shared --disable-libssp
--disable-bootstrap --disable-nls --disable-libquadmath --with-newlib
--enable-lto --enable-languages=c
--with-gmp=/home/marc/devel/coreboot/util/crossgcc/xgcc
--with-mpfr=/home/marc/devel/coreboot/util/crossgcc/xgcc
--with-mpc=/home/marc/devel/coreboot/util/crossgcc/xgcc
--with-libelf=/home/marc/devel/coreboot/util/crossgcc/xgcc
--with-pkgversion='coreboot toolchain v1.07 November 1st, 2011'
Thread model: single
gcc version 4.6.2 (coreboot toolchain v1.07 November 1st, 2011)
tint.elf and objdump -D files attached.
My git repo if you would like try this exact code:
git://git.se-eng.com/coreboot.git
Questions or comments?
Marc
--
http://se-eng.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: tint-gcc462bug.tar.gz
Type: application/x-gzip
Size: 479907 bytes
Desc: not available
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20120228/14b0163a/attachment.gz>
More information about the coreboot
mailing list