1 #!/usr/bin/env perl 2 # SPDX-License-Identifier: GPL-2.0 3 4 BEGIN { $Pod::Usage::Formatter = 'Pod::Text::T 5 6 use strict; 7 use warnings; 8 use utf8; 9 use Pod::Usage qw(pod2usage); 10 use Getopt::Long; 11 use File::Find; 12 use IO::Handle; 13 use Fcntl ':mode'; 14 use Cwd 'abs_path'; 15 use Data::Dumper; 16 17 my $help = 0; 18 my $hint = 0; 19 my $man = 0; 20 my $debug = 0; 21 my $enable_lineno = 0; 22 my $show_warnings = 1; 23 my $prefix="Documentation/ABI"; 24 my $sysfs_prefix="/sys"; 25 my $search_string; 26 27 # Debug options 28 my $dbg_what_parsing = 1; 29 my $dbg_what_open = 2; 30 my $dbg_dump_abi_structs = 4; 31 my $dbg_undefined = 8; 32 33 $Data::Dumper::Indent = 1; 34 $Data::Dumper::Terse = 1; 35 36 # 37 # If true, assumes that the description is for 38 # 39 my $description_is_rst = 1; 40 41 GetOptions( 42 "debug=i" => \$debug, 43 "enable-lineno" => \$enable_lineno, 44 "rst-source!" => \$description_is_rst, 45 "dir=s" => \$prefix, 46 'help|?' => \$help, 47 "show-hints" => \$hint, 48 "search-string=s" => \$search_string, 49 man => \$man 50 ) or pod2usage(2); 51 52 pod2usage(1) if $help; 53 pod2usage(-exitstatus => 0, -noperldoc, -verbo 54 55 pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2) 56 57 my ($cmd, $arg) = @ARGV; 58 59 pod2usage(2) if ($cmd ne "search" && $cmd ne " 60 pod2usage(2) if ($cmd eq "search" && !$arg); 61 62 require Data::Dumper if ($debug & $dbg_dump_ab 63 64 my %data; 65 my %symbols; 66 67 # 68 # Displays an error message, printing file nam 69 # 70 sub parse_error($$$$) { 71 my ($file, $ln, $msg, $data) = @_; 72 73 return if (!$show_warnings); 74 75 $data =~ s/\s+$/\n/; 76 77 print STDERR "Warning: file $file#$ln: 78 79 if ($data ne "") { 80 print STDERR ". Line\n\t\t$dat 81 } else { 82 print STDERR "\n"; 83 } 84 } 85 86 # 87 # Parse an ABI file, storing its contents at % 88 # 89 sub parse_abi { 90 my $file = $File::Find::name; 91 92 my $mode = (stat($file))[2]; 93 return if ($mode & S_IFDIR); 94 return if ($file =~ m,/README,); 95 return if ($file =~ m,/\.,); 96 return if ($file =~ m,\.(rej|org|orig| 97 98 my $name = $file; 99 $name =~ s,.*/,,; 100 101 my $fn = $file; 102 $fn =~ s,.*Documentation/ABI/,,; 103 104 my $nametag = "File $fn"; 105 $data{$nametag}->{what} = "File $name" 106 $data{$nametag}->{type} = "File"; 107 $data{$nametag}->{file} = $name; 108 $data{$nametag}->{filepath} = $file; 109 $data{$nametag}->{is_file} = 1; 110 $data{$nametag}->{line_no} = 1; 111 112 my $type = $file; 113 $type =~ s,.*/(.*)/.*,$1,; 114 115 my $what; 116 my $new_what; 117 my $tag = ""; 118 my $ln; 119 my $xrefs; 120 my $space; 121 my @labels; 122 my $label = ""; 123 124 print STDERR "Opening $file\n" if ($de 125 open IN, $file; 126 while(<IN>) { 127 $ln++; 128 if (m/^(\S+)(:\s*)(.*)/i) { 129 my $new_tag = lc($1); 130 my $sep = $2; 131 my $content = $3; 132 133 if (!($new_tag =~ m/(w 134 if ($tag eq "d 135 # New 136 # desc 137 $new_t 138 } elsif ($tag 139 parse_ 140 } 141 } 142 143 # Invalid, but it is a 144 if ($new_tag eq "where 145 parse_error($f 146 $new_tag = "wh 147 } 148 149 if ($new_tag =~ m/what 150 $space = ""; 151 $content =~ s/ 152 153 push @{$symbol 154 155 if ($tag =~ m/ 156 $what 157 } else { 158 if ($w 159 160 161 162 163 164 } 165 166 $what 167 $label 168 $new_w 169 } 170 push @labels, 171 $tag = $new_ta 172 173 push @{$data{$ 174 next; 175 } 176 177 if ($tag ne "" && $new 178 $tag = $new_ta 179 180 if ($new_what) 181 @{$dat 182 @label 183 $label 184 $new_w 185 186 $data{ 187 if (!d 188 189 190 } else 191 192 193 194 195 196 } 197 print 198 $data{ 199 } else { 200 $data{ 201 } 202 203 if (!$what) { 204 parse_ 205 next; 206 } 207 if ($new_tag e 208 $sep = 209 $conte 210 while 211 if ($c 212 213 214 215 216 } else 217 218 } 219 220 } else { 221 $data{ 222 } 223 next; 224 } 225 } 226 227 # Store any contents before ta 228 if (!$tag && $data{$nametag}-> 229 $data{$nametag}->{desc 230 next; 231 } 232 233 if ($tag eq "description") { 234 my $content = $_; 235 while ($content =~ s/\ 236 if (m/^\s*\n/) { 237 $data{$what}-> 238 next; 239 } 240 241 if (!defined($space)) 242 # Preserve ini 243 if ($content = 244 $space 245 $conte 246 } 247 } else { 248 $space = "" if 249 } 250 $data{$what}->{$tag} . 251 252 next; 253 } 254 if (m/^\s*(.*)/) { 255 $data{$what}->{$tag} . 256 $data{$what}->{$tag} = 257 next; 258 } 259 260 # Everything else is error 261 parse_error($file, $ln, "Unexp 262 } 263 $data{$nametag}->{description} =~ s/^\ 264 if ($what) { 265 parse_error($file, $ln, "What 266 267 foreach my $w(split /\xac/,$wh 268 $symbols{$w}->{xref} = 269 }; 270 } 271 close IN; 272 } 273 274 sub create_labels { 275 my %labels; 276 277 foreach my $what (keys %data) { 278 next if ($data{$what}->{file} 279 280 foreach my $p (@{$data{$what}- 281 my ($content, $label) 282 $label = "abi_" . $lab 283 $label =~ tr/A-Z/a-z/; 284 285 # Convert special char 286 $label =~s/([\x00-\x2f 287 $label =~ s,_+,_,g; 288 $label =~ s,_$,,; 289 290 # Avoid duplicated lab 291 while (defined($labels 292 my @chars = ("A".. 293 $label .= $chars[r 294 } 295 $labels{$label} = 1; 296 297 $data{$what}->{label} 298 299 # only one label is en 300 last; 301 } 302 } 303 } 304 305 # 306 # Outputs the book on ReST format 307 # 308 309 # \b doesn't work well with paths. So, we need 310 # Boundaries are punct characters, spaces and 311 my $start = qr {(^|\s|\() }x; 312 my $bondary = qr { ([,.:;\)\s]|\z) }x; 313 my $xref_match = qr { $start(\/(sys|config|pro 314 my $symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x 315 316 sub output_rest { 317 create_labels(); 318 319 my $part = ""; 320 321 foreach my $what (sort { 322 ($data{$a}->{t 323 $a cmp $b 324 } keys %data) { 325 my $type = $data{$what}->{type 326 327 my @file = split / /, $data{$w 328 my @filepath = split / /, $dat 329 330 if ($enable_lineno) { 331 printf ".. LINENO %s%s 332 $prefix, $file[ 333 $data{$what}->{ 334 } 335 336 my $w = $what; 337 338 if ($type ne "File") { 339 my $cur_part = $what; 340 if ($what =~ '/') { 341 if ($what =~ m 342 $cur_p 343 $cur_p 344 } 345 } 346 347 if ($cur_part ne "" && 348 $part = $cur_part; 349 my $bar = $part; 350 $bar =~ s/./-/g; 351 print "$part\n$bar 352 } 353 354 printf ".. _%s:\n\n", 355 356 my @names = split /\xa 357 my $len = 0; 358 359 foreach my $name (@nam 360 $name =~ s/$sy 361 $name = "**$na 362 $len = length( 363 } 364 365 print "+-" . "-" x $le 366 foreach my $name (@nam 367 printf "| %s", 368 print "+-" . " 369 } 370 371 print "\n"; 372 } 373 374 for (my $i = 0; $i < scalar(@f 375 my $path = $filepath[$ 376 my $f = $file[$i]; 377 378 $path =~ s,.*/(.*/.*), 379 $path =~ s,[/\-],_,g;; 380 my $fileref = "abi_fil 381 382 if ($type eq "File") { 383 print ".. _$fi 384 } else { 385 print "Defined 386 } 387 } 388 389 if ($type eq "File") { 390 my $bar = $w; 391 $bar =~ s/./-/g; 392 print "$w\n$bar\n\n"; 393 } 394 395 my $desc = ""; 396 $desc = $data{$what}->{descrip 397 $desc =~ s/\s+$/\n/; 398 399 if (!($desc =~ /^\s*$/)) { 400 if ($description_is_rs 401 # Remove title 402 # Having title 403 # care would b 404 # level order 405 $desc =~ s/\n[ 406 407 # Enrich text 408 409 my $new_desc = 410 my $init_inden 411 my $literal_in 412 413 open(my $fh, " 414 while (my $d = 415 my $in 416 my $sp 417 $init_ 418 if ($l 419 420 421 422 423 424 425 } else 426 427 428 429 } 430 431 $d =~ 432 433 my @ma 434 foreac 435 436 437 438 439 440 441 } 442 443 # Seek 444 @match 445 446 foreac 447 448 449 450 451 452 453 454 455 456 } 457 $new_d 458 } 459 close $fh; 460 461 462 print "$new_de 463 } else { 464 $desc =~ s/^\s 465 466 # Remove title 467 $desc =~ s/\n[ 468 469 if ($desc =~ m 470 # put 471 $desc 472 473 print 474 print 475 } else { 476 # Esca 477 $desc 478 print 479 } 480 } 481 } else { 482 print "DESCRIPTION MIS 483 } 484 485 if ($data{$what}->{symbols}) { 486 printf "Has the follow 487 488 foreach my $content(@{ 489 my $label = $d 490 491 # Escape speci 492 $content =~s/( 493 494 print "- :ref: 495 } 496 } 497 498 if (defined($data{$what}->{use 499 my $users = $data{$wha 500 501 $users =~ s/\n/\n\t/g; 502 printf "Users:\n\t%s\n 503 } 504 505 } 506 } 507 508 # 509 # Searches for ABI symbols 510 # 511 sub search_symbols { 512 foreach my $what (sort keys %data) { 513 next if (!($what =~ m/($arg)/) 514 515 my $type = $data{$what}->{type 516 next if ($type eq "File"); 517 518 my $file = $data{$what}->{file 519 520 $what =~ s/\xac/, /g; 521 my $bar = $what; 522 $bar =~ s/./-/g; 523 524 print "\n$what\n$bar\n\n"; 525 526 my $kernelversion = $data{$wha 527 my $contact = $data{$what}->{c 528 my $users = $data{$what}->{use 529 my $date = $data{$what}->{date 530 my $desc = $data{$what}->{desc 531 532 $kernelversion =~ s/^\s+// if 533 $contact =~ s/^\s+// if ($cont 534 if ($users) { 535 $users =~ s/^\s+//; 536 $users =~ s/\n//g; 537 } 538 $date =~ s/^\s+// if ($date); 539 $desc =~ s/^\s+// if ($desc); 540 541 printf "Kernel version:\t\t%s\ 542 printf "Date:\t\t\t%s\n", $dat 543 printf "Contact:\t\t%s\n", $co 544 printf "Users:\t\t\t%s\n", $us 545 print "Defined on file(s):\t$f 546 print "Description:\n\n$desc"; 547 } 548 } 549 550 # Exclude /sys/kernel/debug and /sys/kernel/tr 551 sub dont_parse_special_attributes { 552 if (($File::Find::dir =~ m,^/sys/kerne 553 return grep {!/(debug|tracing) 554 } 555 556 if (($File::Find::dir =~ m,^/sys/fs,)) 557 return grep {!/(pstore|bpf|fus 558 } 559 560 return @_ 561 } 562 563 my %leaf; 564 my %aliases; 565 my @files; 566 my %root; 567 568 sub graph_add_file { 569 my $file = shift; 570 my $type = shift; 571 572 my $dir = $file; 573 $dir =~ s,^(.*/).*,$1,; 574 $file =~ s,.*/,,; 575 576 my $name; 577 my $file_ref = \%root; 578 foreach my $edge(split "/", $dir) { 579 $name .= "$edge/"; 580 if (!defined ${$file_ref}{$edg 581 ${$file_ref}{$edge} = 582 } 583 $file_ref = \%{$$file_ref{$edg 584 ${$file_ref}{"__name"} = [ $na 585 } 586 $name .= "$file"; 587 ${$file_ref}{$file} = { 588 "__name" => [ $name ] 589 }; 590 591 return \%{$$file_ref{$file}}; 592 } 593 594 sub graph_add_link { 595 my $file = shift; 596 my $link = shift; 597 598 # Traverse graph to find the reference 599 my $file_ref = \%root; 600 foreach my $edge(split "/", $file) { 601 $file_ref = \%{$$file_ref{$edg 602 } 603 604 # do a BFS 605 606 my @queue; 607 my %seen; 608 my $st; 609 610 push @queue, $file_ref; 611 $seen{$start}++; 612 613 while (@queue) { 614 my $v = shift @queue; 615 my @child = keys(%{$v}); 616 617 foreach my $c(@child) { 618 next if $seen{$$v{$c}} 619 next if ($c eq "__name 620 621 if (!defined($$v{$c}{" 622 printf STDERR 623 print STDERR D 624 exit; 625 } 626 627 # Add new name 628 my $name = @{$$v{$c}{" 629 if ($name =~ s#^$file/ 630 push @{$$v{$c} 631 } 632 # Add child to the que 633 push @queue, $$v{$c}; 634 $seen{$c}++; 635 } 636 } 637 } 638 639 my $escape_symbols = qr { ([\x01-\x08\x0e-\x1f 640 sub parse_existing_sysfs { 641 my $file = $File::Find::name; 642 643 my $mode = (lstat($file))[2]; 644 my $abs_file = abs_path($file); 645 646 my @tmp; 647 push @tmp, $file; 648 push @tmp, $abs_file if ($abs_file ne 649 650 foreach my $f(@tmp) { 651 # Ignore cgroup, as this is bi 652 return if ($f =~ m#^/sys/fs/cg 653 654 # Ignore firmware as it is doc 655 # Either ACPI or under Documen 656 return if ($f =~ m#^/sys/firmw 657 658 # Ignore some sysfs nodes that 659 return if ($f =~ m#/sections|n 660 661 # Would need to check at 662 # Documentation/admin-guide/ke 663 # is not easily parseable. 664 return if ($f =~ m#/parameters 665 } 666 667 if (S_ISLNK($mode)) { 668 $aliases{$file} = $abs_file; 669 return; 670 } 671 672 return if (S_ISDIR($mode)); 673 674 # Trivial: file is defined exactly the 675 return if (defined($data{$file})); 676 return if (defined($data{$abs_file})); 677 678 push @files, graph_add_file($abs_file, 679 } 680 681 sub get_leave($) 682 { 683 my $what = shift; 684 my $leave; 685 686 my $l = $what; 687 my $stop = 1; 688 689 $leave = $l; 690 $leave =~ s,/$,,; 691 $leave =~ s,.*/,,; 692 $leave =~ s/[\(\)]//g; 693 694 # $leave is used to improve search per 695 # check_undefined_symbols, as the algo 696 # for a small number of "what". It als 697 # hint about a leave with the same nam 698 # However, there are a few occurences 699 # either a wildcard or a number. Just 700 # altogether. 701 if ($leave =~ m/\.\*/ || $leave eq "" 702 $leave = "others"; 703 } 704 705 return $leave; 706 } 707 708 my @not_found; 709 710 sub check_file($$) 711 { 712 my $file_ref = shift; 713 my $names_ref = shift; 714 my @names = @{$names_ref}; 715 my $file = $names[0]; 716 717 my $found_string; 718 719 my $leave = get_leave($file); 720 if (!defined($leaf{$leave})) { 721 $leave = "others"; 722 } 723 my @expr = @{$leaf{$leave}->{expr}}; 724 die ("\rmissing rules for $leave") if 725 726 my $path = $file; 727 $path =~ s,(.*/).*,$1,; 728 729 if ($search_string) { 730 return if (!($file =~ m#$searc 731 $found_string = 1; 732 } 733 734 for (my $i = 0; $i < @names; $i++) { 735 if ($found_string && $hint) { 736 if (!$i) { 737 print STDERR " 738 } else { 739 print STDERR " 740 } 741 } 742 foreach my $re (@expr) { 743 print STDERR "$names[$ 744 if ($names[$i] =~ $re) 745 return; 746 } 747 } 748 } 749 750 if ($leave ne "others") { 751 my @expr = @{$leaf{"others"}-> 752 for (my $i = 0; $i < @names; $ 753 foreach my $re (@expr) 754 print STDERR " 755 if ($names[$i] 756 return 757 } 758 } 759 } 760 } 761 762 push @not_found, $file if (!$search_st 763 764 if ($hint && (!$search_string || $foun 765 my $what = $leaf{$leave}->{wha 766 $what =~ s/\xac/\n\t/g; 767 if ($leave ne "others") { 768 print STDERR "\r mo 769 } else { 770 print STDERR "\r te 771 } 772 } 773 } 774 775 sub check_undefined_symbols { 776 my $num_files = scalar @files; 777 my $next_i = 0; 778 my $start_time = times; 779 780 @files = sort @files; 781 782 my $last_time = $start_time; 783 784 # When either debug or hint is enabled 785 # progress, as the progress will be ov 786 if ($hint || ($debug && $dbg_undefined 787 $next_i = $num_files; 788 } 789 790 my $is_console; 791 $is_console = 1 if (-t STDERR); 792 793 for (my $i = 0; $i < $num_files; $i++) 794 my $file_ref = $files[$i]; 795 my @names = @{$$file_ref{"__na 796 797 check_file($file_ref, \@names) 798 799 my $cur_time = times; 800 801 if ($i == $next_i || $cur_time 802 my $percent = $i * 100 803 804 my $tm = $cur_time - $ 805 my $time = sprintf "%d 806 807 printf STDERR "\33[2K\ 808 printf STDERR "%s: pro 809 printf STDERR "\n", if 810 STDERR->flush(); 811 812 $next_i = int (($perce 813 $last_time = $cur_time 814 } 815 } 816 817 my $cur_time = times; 818 my $tm = $cur_time - $start_time; 819 my $time = sprintf "%d:%02d", int($tm) 820 821 printf STDERR "\33[2K\r", if ($is_cons 822 printf STDERR "%s: processing sysfs fi 823 824 foreach my $file (@not_found) { 825 print "$file not found.\n"; 826 } 827 } 828 829 sub undefined_symbols { 830 print STDERR "Reading $sysfs_prefix di 831 find({ 832 wanted =>\&parse_existing_sysf 833 preprocess =>\&dont_parse_spec 834 no_chdir => 1 835 }, $sysfs_prefix); 836 print STDERR "done.\n"; 837 838 $leaf{"others"}->{what} = ""; 839 840 print STDERR "Converting ABI What fiel 841 foreach my $w (sort keys %data) { 842 foreach my $what (split /\xac/ 843 next if (!($what =~ m/ 844 845 # Convert what into re 846 847 # Escape dot character 848 $what =~ s/\./\xf6/g; 849 850 # Temporarily change [ 851 $what =~ s/\[0\-9\]\+/ 852 853 # Temporarily change [ 854 $what =~ s/\[0\-\d+\]/ 855 $what =~ s/\[(\d+)\]/\ 856 857 # Temporarily change [ 858 $what =~ s/\[(\d)\-(\d 859 860 # Handle multiple opti 861 $what =~ s/[\{\<\[]([\ 862 863 # Handle wildcards 864 $what =~ s,\*,.*,g; 865 $what =~ s,/\xf6..,/.* 866 $what =~ s/\<[^\>]+\>/ 867 $what =~ s/\{[^\}]+\}/ 868 $what =~ s/\[[^\]]+\]/ 869 870 $what =~ s/[XYZ]/.*/g; 871 872 # Recover [0-9] type o 873 $what =~ s/\xf4/[/g; 874 $what =~ s/\xf5/]/g; 875 876 # Remove duplicated sp 877 $what =~ s/\s+/ /g; 878 879 # Special case: this A 880 $what =~ s/sqrt\(x^2\+ 881 882 # Special case: drop c 883 # What: foo = <s 884 # (this happens on a f 885 $what =~ s,\s*\=.*$,,; 886 887 # Escape all other sym 888 $what =~ s/$escape_sym 889 $what =~ s/\\\\/\\/g; 890 $what =~ s/\\([\[\]\(\ 891 $what =~ s/(\d+)\\(-\d 892 893 $what =~ s/\xff/\\d+/g 894 895 # Special case: IIO AB 896 $what =~ s/sqrt(.*)/sq 897 898 # Simplify regexes wit 899 $what =~ s#(?:\.\*){2, 900 # $what =~ s#\.\*/\.\*#. 901 902 # Recover dot characte 903 $what =~ s/\xf6/\./g; 904 905 my $leave = get_leave( 906 907 my $added = 0; 908 foreach my $l (split / 909 if (defined($l 910 next i 911 $leaf{ 912 $added 913 } else { 914 $leaf{ 915 $added 916 } 917 } 918 if ($search_string && 919 print STDERR " 920 } 921 922 } 923 } 924 # Compile regexes 925 foreach my $l (sort keys %leaf) { 926 my @expr; 927 foreach my $w(sort split /\xac 928 push @expr, qr /^$w$/; 929 } 930 $leaf{$l}->{expr} = \@expr; 931 } 932 933 # Take links into account 934 foreach my $link (sort keys %aliases) 935 my $abs_file = $aliases{$link} 936 graph_add_link($abs_file, $lin 937 } 938 print STDERR "done.\n"; 939 940 check_undefined_symbols; 941 } 942 943 # Ensure that the prefix will always end with 944 # While this is not needed for find, it makes 945 # with --enable-lineno 946 $prefix =~ s,/?$,/,; 947 948 if ($cmd eq "undefined" || $cmd eq "search") { 949 $show_warnings = 0; 950 } 951 # 952 # Parses all ABI files located at $prefix dir 953 # 954 find({wanted =>\&parse_abi, no_chdir => 1}, $p 955 956 print STDERR Data::Dumper->Dump([\%data], [qw( 957 958 # 959 # Handles the command 960 # 961 if ($cmd eq "undefined") { 962 undefined_symbols; 963 } elsif ($cmd eq "search") { 964 search_symbols; 965 } else { 966 if ($cmd eq "rest") { 967 output_rest; 968 } 969 970 # Warn about duplicated ABI entries 971 foreach my $what(sort keys %symbols) { 972 my @files = @{$symbols{$what}- 973 974 next if (scalar(@files) == 1); 975 976 printf STDERR "Warning: $what 977 scalar(@files); 978 } 979 } 980 981 __END__ 982 983 =head1 NAME 984 985 get_abi.pl - parse the Linux ABI files and pro 986 987 =head1 SYNOPSIS 988 989 B<get_abi.pl> [--debug <level>] [--enable-line 990 [--(no-)rst-source] [--dir=<dir 991 [--search-string <regex>] 992 <COMMAND> [<ARGUMENT>] 993 994 Where B<COMMAND> can be: 995 996 =over 8 997 998 B<search> I<SEARCH_REGEX> - search for I<SEARC 999 1000 B<rest> - output the ABI in 1001 1002 B<validate> - validate the ABI 1003 1004 B<undefined> - existing symbols 1005 defined at Docume 1006 1007 =back 1008 1009 =head1 OPTIONS 1010 1011 =over 8 1012 1013 =item B<--dir> 1014 1015 Changes the location of the ABI search. By de 1016 the Documentation/ABI directory. 1017 1018 =item B<--rst-source> and B<--no-rst-source> 1019 1020 The input file may be using ReST syntax or no 1021 selecting between a rst-compliant source ABI 1022 plain text that may be violating ReST spec, s 1023 logic (B<--no-rst-source>). 1024 1025 =item B<--enable-lineno> 1026 1027 Enable output of .. LINENO lines. 1028 1029 =item B<--debug> I<debug level> 1030 1031 Print debug information according with the le 1032 following bitmask: 1033 1034 - 1: Debug parsing What entries from ABI 1035 - 2: Shows what files are opened from AB 1036 - 4: Dump the structs used to store the 1037 1038 =item B<--show-hints> 1039 1040 Show hints about possible definitions for the 1041 Used only when B<undefined>. 1042 1043 =item B<--search-string> I<regex string> 1044 1045 Show only occurences that match a search stri 1046 Used only when B<undefined>. 1047 1048 =item B<--help> 1049 1050 Prints a brief help message and exits. 1051 1052 =item B<--man> 1053 1054 Prints the manual page and exits. 1055 1056 =back 1057 1058 =head1 DESCRIPTION 1059 1060 Parse the Linux ABI files from ABI DIR (usual 1061 allowing to search for ABI symbols or to prod 1062 the Linux ABI documentation. 1063 1064 =head1 EXAMPLES 1065 1066 Search for all stable symbols with the word " 1067 1068 =over 8 1069 1070 $ scripts/get_abi.pl search usb --dir Documen 1071 1072 =back 1073 1074 Search for all symbols that match the regex e 1075 1076 =over 8 1077 1078 $ scripts/get_abi.pl search usb.*cap 1079 1080 =back 1081 1082 Output all obsoleted symbols in ReST format 1083 1084 =over 8 1085 1086 $ scripts/get_abi.pl rest --dir Documentation 1087 1088 =back 1089 1090 =head1 BUGS 1091 1092 Report bugs to Mauro Carvalho Chehab <mchehab+ 1093 1094 =head1 COPYRIGHT 1095 1096 Copyright (c) 2016-2021 by Mauro Carvalho Che< 1097 1098 License GPLv2: GNU GPL version 2 <http://gnu. 1099 1100 This is free software: you are free to change 1101 There is NO WARRANTY, to the extent permitted 1102 1103 =cut
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.