[LLVMdev] llvm-ranlib: Bus Error in regressions + fix
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
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.
More information about the llvm-dev