#!/usr/bin/perl use strict; sub add_image_subdir { my ($image) = @_; if (!($image =~ m/\/img/)) { $image = "./img/".$image }; return $image; } sub find_symbol_name { my ($offset, $require_function, $symbol_addrs, $symbol_sorted_addrs, $symbol_funcs) = @_; if (defined $symbol_addrs->{$offset}) { for my $sym (@{$symbol_addrs->{$offset}}) { if ($symbol_funcs->{$sym}) { return $sym; } } if ($require_function) { return 0; } return @{$symbol_addrs->{$offset}}[0]; } if ($require_function) { return 0; } my $prevoffset = -1; my $search_first = 0; my $search_last = $#$symbol_sorted_addrs; while ($search_first != $search_last) { my $search_mid = int ($search_first + $search_last) / 2; if ($search_mid == $search_first) { if (@$symbol_sorted_addrs[$search_last] <= $offset) { $search_first = $search_last; } else { $search_last = $search_first; } } elsif (@$symbol_sorted_addrs[$search_mid] <= $offset) { $search_first = $search_mid; } else { $search_last = $search_mid; } } if (@$symbol_sorted_addrs[$search_first] <= $offset) { $prevoffset = @$symbol_sorted_addrs[$search_first]; } if (defined $symbol_addrs->{$prevoffset}) { for my $sym (@{$symbol_addrs->{$prevoffset}}) { if ($symbol_funcs->{$sym}) { return sprintf "%s+0x%x", $sym, ($offset - $prevoffset); } } return sprintf "%s+0x%x", @{$symbol_addrs->{$prevoffset}}[0], ($offset - $prevoffset); } return sprintf "Unknown @ 0x%x", $offset; } use FindBin qw($Bin); my $image_offset = $ENV{"HAL_IMAGE_OFFSET"}; if (not $image_offset) { $image_offset = "0x0"; }; $image_offset = hex $image_offset; my $image; my $all_modules = 0; my @modules = (); if ($#ARGV == -1) { die "genlist [modules]\n"; } if ($#ARGV == 0) { $all_modules = 1; } else { @modules = @ARGV[1..$#ARGV]; } $image = add_image_subdir($ARGV[0]); my %module_offsets = (); open MODINFO, "< $image.modinfo"; while (my $modline = ) { chomp $modline; my @splitline = split /,/, $modline; $module_offsets{@splitline[0]} = (hex @splitline[1]) + $image_offset; if ($all_modules) { push @modules, @splitline[0]; } } my %symbol_address = (); my %symbol_isfunc = (); my $gensyms = $image; $gensyms =~ s/\.bin/\.syms/; open GENSYMS, "<".$gensyms; while (my $line = ) { chomp $line; my ($is_func,$code_addr,$addr,$function); $line =~ m/(.*?),(.*?),(.*?),(.*?),(.*)/; $is_func = "F" eq $1; $addr = hex $2; $function = $5; if (not defined $symbol_address{$addr}) { $symbol_address{$addr} = (); } push @{$symbol_address{$addr}}, $function; $symbol_isfunc{$function} = $is_func; } my @symbol_sorted_addrs = sort { $a <=> $b} keys %symbol_address; foreach my $module (@modules) { print "BEGIN MODULE ---- ".$module." ----\n"; my $enabled = 0; my $sections = 0; open OBJDUMP, ("ppc64-mcp6-objdump -DCS ".add_image_subdir($module)."|"); while (my $line = ) { if (!$enabled && ($sections >= 2)) { close OBJDUMP; } if (($line =~ m/Disassembly/) && ($line =~ m/Disassembly of section/)) { if (($line =~ m/.text/) || ($line =~ m/.data/)) { $enabled = 1; $sections = $sections + 1; } else { $enabled = 0; } } elsif ($enabled) { if ($line =~ s/(^[\s]*)([0-9a-f]+)(:)/$1__HEXVALUE__$3/) { my $value = hex $2; my $offset = $value + $module_offsets{$module}; my $format = sprintf "%x\t%08x", $value, $offset; $line =~ s/__HEXVALUE__/$format/; my $symname = find_symbol_name($offset, 1, \%symbol_address, \@symbol_sorted_addrs, \%symbol_isfunc); if ($symname) { printf "%016x <%s>:\n", $offset, $symname; } if ($line =~ s/(b[a-z]*[+-]*[\s]*(.*,){0,1})([0-9a-f]+)([\s]*<)(.*)(>)/$1__HEXVALUE__$4__FUNCREF__$6/) { $value = hex $3; $offset = $value + $module_offsets{$module}; $format = sprintf "%x", $offset; $line =~ s/__HEXVALUE__/$format/; my $refname = find_symbol_name($offset, 0, \%symbol_address, \@symbol_sorted_addrs, \%symbol_isfunc); $line =~ s/__FUNCREF__/$refname/ } } print $line; } } close OBJDUMP; print "\n"; }