[LLVMdev] llvm-ranlib: Bus Error in regressions + fix

Reid Spencer reid at x10sys.com
Tue Nov 22 16:10:45 PST 2005


Evan Jones wrote:

  > I am pretty certain that this has nothing to do with the C++ library,
> and everything to do with the behaviour of mmap when the file that was 
> mmaped is modified. I actually can reproduce this behaviour with the 
> attached C test case. The program mmaps a file called 'data,' prints the 
> last byte, truncates the file, then tries to read the last byte again. 
> It causes a Bus Error on both the RedHat system and my Mac OS X 
> workstation. Hence, this appears to be valid (or at least common) mmap 
> behaviour.

Yes, this is the correct behavior for mmap in such a situation. The mapped 
file, when it is truncated, invalidates the memory corresponding to truncated 
portion of the file. The memory is taken out of the virtual memory table so 
that any attempt to access generates a, you guessed it, bus error.

> 
> rn-spra1c07:~ ejones$ dd if=/dev/zero of=data bs=1 count=4096
> 4096+0 records in
> 4096+0 records out
> 4096 bytes transferred in 0.067263 secs (60895 bytes/sec)
> rn-spra1c07:~ ejones$ ./mmaptest
> last byte = 0x00
> Bus error
> 
> I can also reproduce it with a minimal LLVM example, also attached. That 
> program needs the "GNU.a" file in the current directory. It opens the 
> archive and scans through all the members, printing out the first byte 
> of each one. Then it truncates the file and repeats that experiment. It 
> also causes a Bus Error.
> 
> Essentially, this is what happens in ArchiveWriter.cpp:429. This bug 
> will be triggered by any archive that has a native symbol table, since 
> that member (foreignST) references data that was mmaped from the 
> original file. All the other members are copied from the temporary 
> archive, so they are not a problem.

The file gets corrupted because it is overwriting itself. The strace showed 
that it opened the same file for reading and writing with 2 file handlers. This 
isn't what the code is supposed to do. The TmpArchive variable in 
ArchiveWriter.cpp is supposed to reference a unique file name and it is not. 
At that point in the ArchiveWriter, it is trying to insert the symbol table. It 
does that by creating a temporary file and mmaping the original file. The 
temporary file is written with the symbol table and then it writes the entire 
content of the mmaped file into the temporary file (single write using mmaped 
pointer).  When that is done, it renames the temporary file to that of the 
original.  The problem is, the temporary and the original are the same file! 
This is a failure of Path::makeUnique, which is system dependent.

I don't have a debugging environment handy to track this down, but I would 
suggest that you break out a debugger and investigate the following:

1. What is the path name associated with TmpArchive? If its the same as the 
path name associated with archPath then that's a bug, probably introduced when 
Path::makeUnique is called from Path::createTemporaryFileOnDisk which is called 
from line 377 of ArchiveWriter.cpp.

2. If item 1. holds, break in Path::makeUnique and see how it is computing the 
temporary name. There are three mechanisms: mkstemp, mktemp, and "manual". I 
don't know which mechanism it is using or why its not creating a unique file 
name. If your Red Hat system is really old, its possible one of the system 
mechanisms is broken and you'll need to adjust the code for the broken (but 
available) library call.

Reid.




More information about the llvm-dev mailing list