#!/usr/bin/lua local posix = require 'posix' local invoker = require 'invoker' local g_pid = arg[1] local g_range = arg[2] local g_start, g_end = nil, nil local function check_args() if type(g_pid) ~= "string" or string.len(g_pid) == 0 then io.stderr:write("Error, invalid PID specified.\n") io.stderr:flush() return false end local maps = string.format("/proc/%s/maps", g_pid) if not posix.access(maps) then io.stderr:write(string.format("Error, invalid PID specified: %s\n", g_pid)) io.stderr:flush() return false end if type(g_range) ~= "string" then io.stderr:write("Error, invalid range specified.\n") io.stderr:flush() return false end local saddr, eaddr = string.match(g_range, "^(%x+)-(%x+)$") if type(saddr) ~= "string" or type(eaddr) ~= "string" then io.stderr:write(string.format("Error, invalid range specified: '%s'\n", g_range)) io.stderr:flush() return false end g_start = saddr g_end = eaddr return true end local function dump_binary() local rexe = string.format("/proc/%s/exe", g_pid) rexe = invoker.readlink(rexe) if type(rexe) == "string" then local exer = string.match(rexe, "/([^/]+)$") if exer then rexe = exer else rexe = "unknown" end else rexe = "unknown" end local binfile = string.format("%s-%s-%s-%s.bin", rexe, g_pid, g_start, g_end) local cmds = { "gdb", "--nx", "--batch", "-ex", "set pagination off", "-ex", "set height 0", "-ex", "set width 0" } cmds[#cmds + 1] = "-ex" cmds[#cmds + 1] = string.format("attach %s", g_pid) cmds[#cmds + 1] = "-ex" cmds[#cmds + 1] = string.format("dump binary memory %s 0x%s 0x%s", binfile, g_start, g_end) cmds[#cmds + 1] = "-ex" cmds[#cmds + 1] = "detach" cmds[#cmds + 1] = "-ex" cmds[#cmds + 1] = "quit" io.stdout:write(string.format("Calling to write '%s' =>\n'%s'\n", binfile, table.concat(cmds, "' '"))) io.stdout:flush() invoker.invoke(invoker.NOSTDIO, cmds) return true end if not check_args() then os.exit(1) end dump_binary() os.exit(0)