Re: Stack trace on SIGSEGV?

  • From: Mike Pall <mike-1210@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 8 Oct 2012 16:38:04 +0200

Luke Gorrie wrote:
> Can someone tell me if this is a good implementation, or how to
> do it better?

  local function protected(type, base, offset, size)
    type = ffi.typeof(type)
    local bound = (size + 0ULL) / ffi.sizeof(type)
    local tptr = ffi.typeof("$ *", type)
    local wrap = ffi.metatype(ffi.typeof("struct { $ _ptr; }", tptr), {
      __index = function(w, idx)
        assert(idx < bound)
        return w._ptr[idx]
      end,
      __newindex = function(w, idx, val)
        assert(idx < bound)
        w._ptr[idx] = val
      end,
    })
    return wrap(ffi.cast(tptr, ffi.cast("uint8_t *", base) + offset))
  end

This generates machine code that would be identical with e.g.
C++ bounds checking templates.

Here's a simple test:

  local mem = ffi.new("int32_t[400]")
  local t = protected("int32_t", mem, 0, 400*4)

  for i=0,399 do t[i] = i end
  for i=0,399 do assert(t[i] == i) end

And here's the machine code of the two inner loops:

->LOOP:
394cffe0  cmp rbp, 0x190                  Bounds check
394cffe7  jnb 0x394c0024        ->5
394cffed  mov [rax+rbp*4], ebp            Store
394cfff0  add ebp, +0x01                  Loop counter
394cfff3  cmp ebp, 0x18f
394cfff9  jle 0x394cffe0        ->LOOP

->LOOP:
394cff20  cmp rbp, 0x190                  Bounds check
394cff27  jnb 0x394c002c        ->7
394cff2d  cmp ebp, [rcx+rbp*4]            Load + assert
394cff30  jnz 0x394c0030        ->8
394cff36  add ebp, +0x01                  Loop counter
394cff39  cmp ebp, 0x18f
394cff3f  jle 0x394cff20        ->LOOP

Note that the array bound has been constified and that a single
unsigned compare is sufficient.

[BTW: Avoid uint32_t as far as possible in FFI code. int32_t is
almost always a better choice.]

--Mike

Other related posts: