A-A+

符号表symbols小工具

2014年02月07日 Tool 暂无评论

前几周搞xtrabackup到tmysql1.4的迁移,多个库里还有各种全局变量、函数引用,你懂得...周末花点时间搞了一个工具,至少对解决类似问题起到一些帮助。

这个工具用来找define/undefine symbols。对于单独一个.o文件,nm/readelf + bash足够。但如果一个包含N多.o的(动静态)库,想找出内部的undefined symbols就不那么容易。
比如看下面这个例子:
[bash]
// foo.c
int i; /* common */
int j=0; /* bss */
int k=100; /* data */
char *p=0; /* bss */
char *s=""; /* data */
static double PI = 3.1415926; /* data */
extern long x; /* no symbol */
void foo() { /* text */
return;
}

// bar.c
void bar1() { /* text */
return;
}

static void bar2(void) { /* text */
return;
}

extern void foo(void); /* no symbol */
extern void undefined(void); /* no symbol */
void bar3() { /* text */
foo();
undefined();
}

> ar rcs test.a foo.o bar.o
> nm -C test.a # 单凭肉体,本人很难一眼就分辨出foo其实在test.a里已经是定义好了的... [/bash]

这就是这个小脚本的作用。或者是有现成解决方案只是本人孤陋寡闻,也欢迎给我一些指引。
此使用方法如下:

[bash]
> perl symbols_by_type.pl --help
-t, --symbol_type=type Type of symbols [defined | undefined].
-f, --file=obj_file_path Path of valid .o|.so|.a|... file.
-v, --version Get version of this toolkit.
-h, --help Show HOW-TO.

> perl symbols_by_type.pl -t defined -f ./test.a
0000000000000000 T bar1
0000000000000006 t bar2
000000000000000c T bar3
0000000000000008 D s
0000000000000000 B j
0000000000000008 B p
0000000000000000 D k
0000000000000000 T foo
0000000000000010 d PI
0000000000000004 C i

> perl symbols_by_type.pl -t undefined -f ./test.a
U undefined[/bash]

[bash]
#!/usr/bin/perl
use strict;

use Getopt::Long;
use File::Basename;

### // foo.c
### int i; /* common */
### int j=0; /* bss */
### int k=100; /* data */
### char *p=0; /* bss */
### char *s=""; /* data */
### static double PI = 3.1415926; /* data */
### extern long x; /* no symbol */
### void foo() { /* text */
### return;
### }
###
### // bar.c
### void bar1() { /* text */
### return;
### }
###
### static void bar2(void) { /* text */
### return;
### }
###
### extern void foo(void); /* no symbol */
### extern void undefined(void); /* no symbol */
### void bar3() { /* text */
### foo();
### undefined();
### }
###
### > ar rcs test.a foo.o bar.o
### > nm -C test.a # IT'S NOT EASY TO FIND OUT THAT 'foo' IS A DEFINED SYMBOL IN test.a, HOWEVER IT IS UNDEFINED IN bar.o.
###
###
###
### > perl symbols_by_type.pl --help
### -t, --symbol_type=type Type of symbols [defined | undefined].
### -f, --file=obj_file_path Path of valid .o|.so|.a|... file.
### -v, --version Get version of this toolkit.
### -h, --help Show HOW-TO.
###
### > perl symbols_by_type.pl -t defined -f ./test.a
### 0000000000000000 T bar1
### 0000000000000006 t bar2
### 000000000000000c T bar3
### 0000000000000008 D s
### 0000000000000000 B j
### 0000000000000008 B p
### 0000000000000000 D k
### 0000000000000000 T foo
### 0000000000000010 d PI
### 0000000000000004 C i
###
### > perl symbols_by_type.pl -t undefined -f ./test.a
### U undefined

###################################################################
my $my_type = undef;
my $my_path = undef;
my ($defined, $
undefined) = ("defined", "undefined");
GetOptions(
"type|t:s" => $my_type,
"file|f:s" => $my_path,
"version|v!" => sub {&print_version and exit(0)},
'help!' => sub {&print_version and &print_usage},
) or print_usage();
print("********* Please specify valid type! *********n") and
print_usage() if ! $my_type or ($my_type ne $defined and $my_type ne $undefined);
print("********* Please specify valid obj file path! *********n") and
exit(1) if ! $my_path;
die("********* Obj file specified by file option is not a UN-EMPTY & READABLE file! *********n")
if ! -e $my_path or ! -r $my_path or ! -f $my_path or -z $my_path;

&main;

######################################################################
sub main
{
my %symbols_dic = ();
open(my $fp, "/usr/bin/nm -C " . $my_path . " | ") or die "$!";
while (<$fp>) {
chomp;
# print "ERROR PARSING: $_n" and next unless /([ws]+)s+?([w])s+?(.+)/;
next unless /([ws]+)s+?([w])s+?(.+)/;
my ($symbol_value, $symbol_type, $symbol_name) = (my_trim($1), my_trim($2), my_trim($3));
# print "$symbol_value, $symbol_type, $symbol_namen";
if (! exists $symbols_dic{$symbol_name}) {
$symbols_dic{$symbol_name} = [];
push @{$symbols_dic{$symbol_name}}, ($symbol_type, $symbol_value);
} else {
my $exist_symbol_type = @{$symbols_dic{$symbol_name}}[0];
if (uc $exist_symbol_type eq "U" and uc $symbol_type ne "U") {
pop @{$symbols_dic{$symbol_name}};
pop @{$symbols_dic{$symbol_name}};
push @{$symbols_dic{$symbol_name}}, $symbol_type;
push @{$symbols_dic{$symbol_name}}, $symbol_value;
}
}
}

foreach my $symbol_name (keys %symbols_dic) {
my ($symbol_type, $symbol_value) = @{$symbols_dic{$symbol_name}};
if (uc $my_type eq uc $defined) {
next if uc $symbol_type eq "U";
print "$symbol_valuet$symbol_typet$symbol_namen";
} elsif (uc $my_type eq uc $undefined) {
next unless uc $symbol_type eq "U";
print "$symbol_valuet$symbol_typet$symbol_namen";
}
}

close($fp);
exit(0);
}

sub my_trim
{
(my $str = $_[0]) =~ s/^s+|s+$//g;
return $str;
}

sub print_version
{
my $version = "v1.0";
print "#######################################\n";
print "##### Initial Version Authors ######\n";
print "##### <harryczhang@tencent.com> ######\n";
print "##### Since Feb 2014 ######\n";
print "#######################################\n";
print basename($0) . ": Version $versionn";
print "#######################################\n";
}

sub print_usage
{
my $info = [
["-t, --symbol_type=type" => "Type of symbols [defined | undefined]."],
["-f, --file=obj_file_path" => "Path of valid .o|.so|.a|... file."],
["-v, --version" => "Get version of this toolkit."],
["-h, --help" => "Show HOW-TO."],
];

foreach(@$info) {
printf("%-40s%-60sn",$_->[0],$_->[1]);
}

exit(0);
}
[/bash]

或者,你可以在这里找到最新的代码:https://github.com/bigdatapi/sugarbox/blob/master/src/perl/symbols_by_type.pl

原创文章,转载请注明: 转载自腾讯游戏DBA团队

本文链接地址: 符号表symbols小工具

文章的脚注信息由WordPress的wp-posturl插件自动生成

标签:
Copyright © 腾讯游戏DBA团队 保留所有权利.  

用户登录

分享到: