/
find_gdb_offset
executable file
·96 lines (75 loc) · 2.68 KB
/
find_gdb_offset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/perl
use File::Temp qw/ tempfile /;
use POSIX;
sub usage
{
print "Usage: find_gdb_offset socket_inode\n";
print "Attempt to find offset to use gdb without debug symbols, without debug symbols =)\n";
exit 1;
}
($ARGV[0] eq "--help") && usage();
(getuid() != 0) && die "must be root.";
print "Note: If you have the kernel's debug symbols you don't need this. Just run:\n";
print " # gdb /usr/src/linux/vmlinux /proc/kcore\n";
print " (gdb) print (int*)(&((struct unix_sock*)0x0)->peer) - (int*)(0x0)\n";
print "to find the right offset.\n\n";
#my $debug = 1;
#######################################################################
# Use lsof to map pids/sockets/kernel addresses
my %inode_to_pid;
my %pid_to_name;
my %address_to_inode;
my %inode_to_address;
sub init_lsof
{
my @lsof = split('\n', `lsof -U +c 0 2>/dev/null` || die "couldn't run lsof");
shift @lsof; # remove header
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# Xorg 982 root 31u unix 0xed0b4400 0t0 6820 /tmp/.X11-unix/X0
foreach my $str (@lsof)
{
$str =~ s/ */ /g;
my ($name, $pid, $z, $z, $z, $address, $z, $inode) = split(' ', $str);
$inode_to_pid{$inode} = $pid;
$pid_to_name{$pid} = $name;
$address_to_inode{$address} = $inode;
$inode_to_address{$inode} = $address;
if ($debug) { print "inode $inode -> address $address ($pid $name)\n"; }
}
}
#######################################################################
sub find_gdb_offset
{
my ($inode) = @_;
my $address = $inode_to_address{$inode};
if ($debug) { print "running gdb ...\n"; }
my $gdb_cmd="";
for (my $i = 5; $i < 200; $i++)
{ $gdb_cmd .= "p ((void **)$address)[$i]\n"; }
my ($fh, $temp_file) = tempfile("/tmp/netstat_unix.XXXXXXXX", UNLINK => 1);
print $fh $gdb_cmd; close($fh);
my @gdb = split('\n', `gdb /dev/null /proc/kcore --batch -x $temp_file 2>/dev/null` || die "couldn't run gdb");
# $1 = (void *) 0xed289000
my $i = 4;
foreach my $str (@gdb)
{
# print "$str\n";
if ($str =~ m|\(void \*\) (0x[0-9a-f]*)|)
{
$i++;
my $peer_address = $1;
my $peer_inode = $address_to_inode{$peer_address} || next;
# print "kernel $peer_address -> inode $peer_inode\n";
print "Offset found, now change hardcoded values in the scripts to:\n";
print " my \$struct_unix_sock__peer_offset=$i;\n";
exit 0;
}
}
}
#######################################################################
my $inode = @ARGV[0];
if (!($inode =~ m|[0-9]+|))
{ usage(); }
init_lsof();
$inode_to_pid{$inode} || die("$inode: No process owns this socket. bad number ?\n");
find_gdb_offset($inode);