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