Skip to content
Prev 46034 / 63424 Next

load/unload segfault puzzle

You can also read the process map table in /proc/<pid>/maps to see which
shared object is associated with the illegal address that valgrind identified.
Read the map table after each load or unload of a *.so with
   map <- readProcessMaps()
and use something like
   subset(map, startAddr <= badAddr & badAddr < endAddr)
to see where the bad address  is.  The "<BSS>" lines are uninitialized memory
required by a shared object (or executable), I believe the object mentioned
in the previous line.  A shared object may have a _fini procedure that refers to
an address in a shared object that got unloaded (_fini might call C++ destructors).

Here is some code to read the map table for the current process.  I did a quick
check of the code on both 32- and 64-bit Linux.  My 32-bit machine does not
have a recent version of R on it so there is some wierd code to work around that.

readProcessMaps <- function()
{
    # Read /proc/$CWD/maps into a data.frame.  This shows which
    # memory addresses are associated with which shared objects
    # at the current time.
    #
    # there are some hacks to make this work in R-2.10.1 (2009), the only
    # version I have compiled for 32-bit Linux.
    #   * as.hexmode() only accepted a scalar
    #   * read.table() did not have a text= argument
    txt <- readLines(file.path("/proc", Sys.getpid(), "maps"))
    nFields <- count.fields(textConnection(txt))
    txt[nFields == 5] <- paste(txt[nFields == 5], "<BSS>")
    txt <- sub("-", " ", txt)
    colNames <- c("startAddr", "endAddr", "perms", "offset", "dev", "inode", "pathname")
    # retval <- read.table(text=txt, col.names=colNames, colClasses="character")
    retval <- read.table(textConnection(txt), col.names=colNames, colClasses="character")
    hex64StringToDouble <- function(s) {
        # as.hexmode only works up to 2^31-1, so we
        # convert 64-bit address nibble by nibble into a double.
        n <- nchar(s)
        acc <- numeric(length(s))
        for(shift in (0:3)*16) {
            # nibble <- as.integer(as.hexmode(substring(s, n-3, n)))
            nibble <- as.integer(sapply(substring(s, n-3, n), as.hexmode))
            n <- n - 4
            acc <- acc + 2^shift * nibble
        }
        acc
    }
    retval[["startAddr"]] <- hex64StringToDouble(retval[["startAddr"]])
    retval[["endAddr"]] <- hex64StringToDouble(retval[["endAddr"]])
    retval
}

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com