[3/4] Add support for undefined symbols in the BTF reader

Message ID 87h6h83g0x.fsf@redhat.com
State New
Headers
Series Support undefined interfaces to fix abicompt's weak mode |

Commit Message

Dodji Seketeli March 14, 2024, 5 p.m. UTC
  Hello,

This patch teaches the BTF reader how to construct an IR for undefined
interfaces.  The patch also updates the abicompat tool for BTF
support.

	* doc/manuals/abicompat.rst: Update documentation for the --btf
	option of abicompat.
	* include/abg-elf-reader.h
	(elf::reader::{function,variable}_symbol_is_undefined): Declare
	new member functions.
	* src/abg-btf-reader.cc
	(reader::read_debug_info_into_corpus): Sort functions &
	variables after canonicalization.
	(reader::build_ir_node_from_btf_type): Always call
	fe_iface::add_{fn,var}_to_exported_or_undefined_decls with the
	decl that was constructed.
	(reader::build_function_decl): Support setting an undefined symbol
	to the function decl.
	(reader::build_var_decl): Likewise, support setting undefined
	symbol the variable decl.
	* src/abg-elf-reader.cc
	((elf::reader::{function,variable}_symbol_is_undefined): Declare
	new member functions.): Define new member functions.
	* src/abg-symtab-reader.cc
	(symtab::{function,variable}_symbol_is_undefined): Return the
	undefined symbol that was found.
	* src/abg-symtab-reader.h
	(symtab::{function,variable}_symbol_is_undefined): Return an
	undefined symbol rather than just a boolean value.
	* tools/abicompat.cc: Add support for BTF here.
	(options::use_btf): Define new data member ...
	(options::options): ... and initialize it.
	(display_usage): Add a help string for the --btf option.
	(parse_command_line): Parse the --btf option.
	* tests/data/test-abicompat/test7-fn-changed-report-0.1.txt: New
	reference test output file.
	* tests/data/test-abicompat/test7-fn-changed-report-2.1.txt:
	Likewise.
	* tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v0.so:
	New binary input file.
	* tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so:
	Likewise.
	* tests/data/test-abicompat/test7-fn-changed-app.btf: Likewise.
	* tests/data/Makefile.am: Add the new test material to source
	distribution.
	* tests/test-abicompat.cc (in_out_specs): Add the new test input
	to the test harness.
	* tests/data/test-abicompat/test7-fn-changed-app.c: Adjust.
	* tests/data/test-abicompat/test7-fn-changed-libapp-v0.c:
	Likewise.
	* tests/data/test-abicompat/test7-fn-changed-libapp-v1.c: Likewise

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 doc/manuals/abicompat.rst                     |   5 +++
 include/abg-elf-reader.h                      |   6 ++++
 src/abg-btf-reader.cc                         |  25 +++++++--------
 src/abg-elf-reader.cc                         |  19 +++++++++++
 src/abg-symtab-reader.cc                      |  30 +++++++++++++-----
 src/abg-symtab-reader.h                       |   4 +--
 tests/data/Makefile.am                        |   5 +++
 .../libtest7-fn-changed-libapp-btf-v0.so      | Bin 0 -> 16560 bytes
 .../libtest7-fn-changed-libapp-btf-v1.so      | Bin 0 -> 16584 bytes
 .../test-abicompat/test7-fn-changed-app.btf   | Bin 0 -> 17536 bytes
 .../test-abicompat/test7-fn-changed-app.c     |   2 ++
 .../test7-fn-changed-libapp-v0.c              |   2 ++
 .../test7-fn-changed-libapp-v1.c              |   3 ++
 .../test7-fn-changed-report-0.1.txt           |  19 +++++++++++
 .../test7-fn-changed-report-2.1.txt           |  16 ++++++++++
 tests/test-abicompat.cc                       |  22 +++++++++++++
 tools/abicompat.cc                            |  18 +++++++++++
 17 files changed, 153 insertions(+), 23 deletions(-)
 create mode 100755 tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v0.so
 create mode 100755 tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so
 create mode 100755 tests/data/test-abicompat/test7-fn-changed-app.btf
 create mode 100644 tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
 create mode 100644 tests/data/test-abicompat/test7-fn-changed-report-2.1.txt

new file mode 100755
index 0000000000000000000000000000000000000000..8970d55a2ea6ae8718997c2b639ea8787647de68
GIT binary patch
literal 16584
zcmeHOU2GKB6~43l*<jcWP)Z?z5dy`~cx+6dqzLd2HcN^L1zRmm>16DgwKv@#vpWkm
zs#>?C5eP*}q^Rvnm8VKPRZ;uWK2$QLqR>_mNU4;kibjfRl&VnCRt{>|e&^nEmi4fX
zA|BG0InteT&v(wb_w1Rwckb-o`@O!y{RzubLJQPB^-xl(ixuhT#DcKhY8kE@)Kl7a
z;X~CUwedv;60TB4rarWaWx<7?;vj?zPO$FJHtnbgf0tq5^?r+?yW3_A?(Ut-?SzqA
znTsEZ<k#dFebc_Ve467F-elA|MvC(iw-@CdY$rVG_a6I2`DXSLu5$tG_y?i?IQ<=E
zzgF8c9OcrFaOv->@T0tZT9Vs*jQgAKKBV|_3+MFeeA?)Y#>~MZLl}3~G{w@4LX=>+
z-hMUk1t?_y@!6L?UU0{EPHmg8|MmX;cNVRBQ-?42m;5x)wGg+y$<%?p^Ud?iRyA*v
z@PW)FQrL4LExEX^Y=Bcgb_4vGdGLPVn;O^;0b8kBRPz%?xq)p?F#a^-dl*-)JDM*R
z+;ZrZLf2L9p}_&y4@$vkwj2hf!GYdfu@DS;!@0od8f)B<3D3=B3tldJHc+1LtMO8{
z5SnX7<+8&gPPyppQU?zo>gjbmola*bBCzQG)UFf~Nf~fSY-L>*w=$u|NePngr+hCI
zf1X+X-U>b~4aoP>xGPL!ny&3PobD~<Ug$<0PGdyqy*gaRI_YlJ;XI`omoCGWfbr1P
zKvNw)$KII7*Ej=l2I36F8Hh6wXCTf%oPjt4|CbEhOK!NIKKJ*g^u<M&+m%ZHa5_v>
zZ=}!tuIY-7r@HeGfU8^ngllqR7iuJrk?!`bDrn1ZNv5Us?Hdr&ukHOcfb?sNenITH
z+3<5{`dd^-)6Lae$&FLwe1$peFKGLnKOnaCLHfeo^yPo-PhXy0khZR-Z$1cDqk%SV
zps9K*liYaVp+ChxwYLvyRr%sj`rO{7R83#_AZ$U?8}PP2a{^(___$nM^c0lVN%URo
zpZss1fpQ2w_mWTa{TG*k*?Y+p)xO?`+B4H9uNZBr&(0+8T)&t6#<fg3`Q7X3i$iNK
z_N7oST)uD>pZVu2sPEtZiqbK2^Fg)x`bng*mg8Dhp^hoeK%9X%191l848$3TGZ1GW
z&On@jI0JD8;tYI-85k-T?7j9D-)^>#c=>?p<!1Y6P#Osep*O05%u>8HuV1idGvcEE
z%4Y9Wt6kuKy<4r)F9B8X^Wa4EpDU4d_L#CJQr7yGB~7p6b(nmgM0p#&9b~W~)xTox
z^T}mrnx@qLb$hn$*sTBNBpbZmt5axG|EJl#BK2ybclqKIXb3pzeUu{f`oB%lpEi1^
zVu~{mXCTf%oPjt4aR%ZH#2JV)5N9CHK%4=}0PmxW?wgdok+dh1sKv0_2F>Lx`|SS(
zmSvyjdY0)OjcA==O7?5gdmEAH|NWp^)Btb3ls%F&EYp5XqE?pi3aaTl%$G4=%bd;B
z4DZvFy_ou46E^Z*O8Yd4K5v-n;*JIX$wH%$I4`lC>@$}B@ZYYEe}e7t53-gek9a-R
zvfh-9Ha=om;^byOGba1iqaE(z{j>ed5BBzc*>1&->8<wmXPpjbyWQE*`D{mL=We_8
zSm4`fFJwhq$5!>$hnA9z<nYm{q)<2u7G<#uWtHjHqGZ`z!1TETvf<737Tq-pq#Fe!
zdTW4X)>~g=ncK5oWSRT3e3mH=U>uH0$Xx`yw630@(Ue8O-C0PV=M;*Jhzja7`npi2
zQ1BPO=4Zh{DT;w<seDTi=W_9{eUsP-!DzFks3aK^`xao-{tD(7QHQRDa`Iyoz%BFz
z{3+M<4s&eW9<?ila(1+U8$`RY8w(?2UP+b5iluO_H9OX+sSPT+WvXc1@v!3KM<G=y
z7gPbi6{$?F=wa)3?YAP?1%A4im3`r~L%e;gm=D_hqW^NXeKZ@kW0SZyoE`PDx%MER
z4cjUOKfspqz;DZDypf>X9tP#G-0pj!r>kwS9x3L>y-<r^YReSb5Kv(h9@N(Oc-!gi
z&WKWF<*8w0hDL!N&Pdn6?#<Q?Z@W6m<6C$m8{?$Z8n$g@BlBO5=fOrc(ueHLZ)7vf
z{=y&EMq*w62{B8or?^j~XI?_e)I#;oYSe&+YywXO`D~)65lr|L_b>P+#-}6rZr~PX
z-&B{er2dEwpjbH3AkPa8;__`2YG0mPf}cUf0w~WP!GDBGqxgS05B?k7PD<UdQHfBa
zcK!&P1irvB4#edqDi+OieC|N-zi525iq5}((*{Y^YKx`e_rWZ+rj{SkE=HmVm*<<{
zPXbTS{1nOaCg8Rh)$x768=V{J(RiI9SBKa>dY<G(;P#{D>g9RxSAf%)c!Wku;V=%N
z6plMZ_3%838|K{+I+0Sw!4<#gj^>KPUe5KyVyWzUl?g=?LM{jc-|1*<L8nx*u2(8~
zlP+eh(xl3iFlo7dC7+*!OP%DxGMr;dGtj*A3?dE+KE><0{l~fo`rN)F2k1x*^+>^#
zi!P=opH9*oIB}$V;7~76JW}1hG&`gZ90P<yH{yEm@C!ZNhus(Y`;Yexx`W+4hx^bV
z#r26Nb!rE2GF|ltZp@jSMkjtg#i^b-Eh(ownGd~T@UUd~nA8fzFmOf-6=%Fu#6uvQ
zR89>Vu4HqV&wZs0#=P>Fa{S2x8Z$gB8O`aSRL&L)a|9Q<Qjqh=fotQrP&qmqP8dv}
zu2b!liu90BPB6x|bIgaYNXEn5SK}dd@}e%#fDXsYXGai15e?(w=-!6QW#wR$<>`^<
z^bGc!81)Bpyf7?fhbtH+kBsNX1Ze$CD+WC6HO+Tkkkz$yw8*rAs`sDo+@RRkty(nH
zjq87~MwR~cA3dbu1#7Fe;<J~i)AOpHz5-zxiulXAUHCK`({dYALCs%QkH>*gSK=@4
z0m5b74--w)Mm^CAkk;VhFY9jMGCj)Y7CYf%@TWDs$g-{%ZgXeR_!(C8JfgP6U*02x
zUt&Y)U-BoP|NHFU!*=psBD|x{e+}wU|BJvVC-UA@dmiuym-jPnM#n03;;*9A``hd%
zT>2LuR@b_DBjPXX1mP<qH%$DcJzm|`;+N;Ea9LT4z2s43UJ=*wuWZ&Ze_9NgOa27@
z87dT_+&_6P3*Rh;%%lC&`l8<dsBH{|zrudPqW#l4gjW9ib*rsw<eY5OUS#3d;Y({V
z@t1YfY#Tt3*cs`eEcl<Hp!mhVwvM5R1tfMxdQ^TN3L1OjFY6sSH$6>_gZOp3)}D-m
z5235?U(Rh_Yu9edHmr7)c!b}DrruxHNi*!<TJtm&@e}?LV5&>}vOZ09%(XX?=}YRw
zAD~eGY)+6S@#i!OtZhjkAEG6wNZlajx{n)tQwAn0qqg+sNb|qY+Lui2-A=>ph(mPz
zk~-3bcAVW|{LizJe#fETQY3FOe>DS>+!+sZo!VviTao@FqF&xN^4~}=3?N$1)>A}O
F{{zL+8D;<g

literal 0
HcmV?d00001

index 90dfe790..813d8aa0 100644
  

Patch

diff --git a/doc/manuals/abicompat.rst b/doc/manuals/abicompat.rst
index e88a05a8..8f19c433 100644
--- a/doc/manuals/abicompat.rst
+++ b/doc/manuals/abicompat.rst
@@ -77,6 +77,11 @@  Options
    Do not show information about where in the *second shared library*
    the respective type was changed.
 
+  * ``--btf``
+
+    When comparing binaries, extract ABI information from BTF debug
+    information, if present.
+
   * ``--ctf``
 
     When comparing binaries, extract ABI information from CTF debug
diff --git a/include/abg-elf-reader.h b/include/abg-elf-reader.h
index ab350607..12f7b026 100644
--- a/include/abg-elf-reader.h
+++ b/include/abg-elf-reader.h
@@ -148,6 +148,12 @@  class reader : public fe_iface
   elf_symbol_sptr
   variable_symbol_is_exported(const string& name) const;
 
+  elf_symbol_sptr
+  function_symbol_is_undefined(const string& name) const;
+
+  elf_symbol_sptr
+  variable_symbol_is_undefined(const string& name) const;
+
   void
   load_dt_soname_and_needed();
 
diff --git a/src/abg-btf-reader.cc b/src/abg-btf-reader.cc
index ce7a7773..25fcb685 100644
--- a/src/abg-btf-reader.cc
+++ b/src/abg-btf-reader.cc
@@ -397,7 +397,8 @@  public:
       }
 
     canonicalize_types();
-
+    corpus()->sort_functions();
+    corpus()->sort_variables();
     return corpus();
   }
 
@@ -504,15 +505,9 @@  public:
     associate_artifact_to_btf_type_id(result, type_id);
 
     if (function_decl_sptr fn = is_function_decl(result))
-      {
-	if (fn->get_is_in_public_symbol_table())
-	  add_fn_to_exported_or_undefined_decls(fn.get());
-      }
+      add_fn_to_exported_or_undefined_decls(fn.get());
     else if (var_decl_sptr var = is_var_decl(result))
-      {
-	if (var->get_is_in_public_symbol_table())
-	  add_var_to_exported_or_undefined_decls(var.get());
-      }
+      add_var_to_exported_or_undefined_decls(var.get());
 
     return result;
   }
@@ -1021,10 +1016,12 @@  public:
 				   location(), /*linkage_name=*/fn_name));
 
     elf_symbol_sptr fn_sym;
-    if ((fn_sym = function_symbol_is_exported(fn_name)))
+    if ((fn_sym = function_symbol_is_exported(fn_name))
+	|| (fn_sym = function_symbol_is_undefined(fn_name)))
       {
 	result->set_symbol(fn_sym);
-	result->set_is_in_public_symbol_table(true);
+	if (fn_sym->is_defined())
+	  result->set_is_in_public_symbol_table(true);
       }
     return result;
   }
@@ -1055,10 +1052,12 @@  public:
 			      /*linkage_name=*/var_name));
 
     elf_symbol_sptr var_sym;
-    if ((var_sym = variable_symbol_is_exported(var_name)))
+    if ((var_sym = variable_symbol_is_exported(var_name))
+	|| (var_sym = variable_symbol_is_undefined(var_name)))
       {
 	result->set_symbol(var_sym);
-	result->set_is_in_public_symbol_table(true);
+	if (var_sym->is_defined())
+	  result->set_is_in_public_symbol_table(true);
       }
     return result;
   }
diff --git a/src/abg-elf-reader.cc b/src/abg-elf-reader.cc
index 14f8ce6a..cbb20dd4 100644
--- a/src/abg-elf-reader.cc
+++ b/src/abg-elf-reader.cc
@@ -890,6 +890,25 @@  reader::variable_symbol_is_exported(const string& name) const
     }
   return elf_symbol_sptr();
 }
+
+/// Test if a name is the name of an undefined function symbol.
+///
+/// @param name the symbol name to consider.
+///
+/// @return the undefined function symbol or nil if none was found.
+elf_symbol_sptr
+reader::function_symbol_is_undefined(const string& name) const
+{return symtab()->function_symbol_is_undefined(name);}
+
+/// Test if a name is the name of an undefined variable symbol.
+///
+/// @param name the symbol name to consider.
+///
+/// @return the undefined variable symbol or nil if none was found.
+elf_symbol_sptr
+reader::variable_symbol_is_undefined(const string& name) const
+{return symtab()->variable_symbol_is_undefined(name);}
+
 /// Load the DT_NEEDED and DT_SONAME elf TAGS.
 void
 reader::load_dt_soname_and_needed()
diff --git a/src/abg-symtab-reader.cc b/src/abg-symtab-reader.cc
index 51177369..fc0cac59 100644
--- a/src/abg-symtab-reader.cc
+++ b/src/abg-symtab-reader.cc
@@ -257,26 +257,40 @@  symtab::variable_symbol_is_exported(const GElf_Addr symbol_address)
 ///
 /// @param sym_name the symbol name to consider.
 ///
-/// @return true iff @p sym_name is the name of a an undefined
-/// function symbol.
-bool
+/// @return the undefined symbol if found, nil otherwise.
+elf_symbol_sptr
 symtab::function_symbol_is_undefined(const string& sym_name)
 {
   collect_undefined_fns_and_vars_linkage_names();
-  return undefined_function_linkage_names_.count(sym_name);
+  if (undefined_function_linkage_names_.count(sym_name))
+    {
+      elf_symbol_sptr sym = lookup_undefined_function_symbol(sym_name);
+      ABG_ASSERT(sym);
+      ABG_ASSERT(sym->is_function());
+      ABG_ASSERT(!sym->is_defined());
+      return sym;
+    }
+  return elf_symbol_sptr();
 }
 
 /// Test if a name is a the name of an undefined variable symbol.
 ///
 /// @param sym_name the symbol name to consider.
 ///
-/// @return true iff @p sym_name is the name of a an undefined
-/// variable symbol.
-bool
+// @return the undefined symbol if found, nil otherwise.
+elf_symbol_sptr
 symtab::variable_symbol_is_undefined(const string& sym_name)
 {
   collect_undefined_fns_and_vars_linkage_names();
-  return undefined_variable_linkage_names_.count(sym_name);
+  if (undefined_variable_linkage_names_.count(sym_name))
+    {
+      elf_symbol_sptr sym = lookup_undefined_variable_symbol(sym_name);
+      ABG_ASSERT(sym);
+      ABG_ASSERT(sym->is_variable());
+      ABG_ASSERT(!sym->is_defined());
+      return sym;
+    }
+  return elf_symbol_sptr();
 }
 
 /// A symbol sorting functor.
diff --git a/src/abg-symtab-reader.h b/src/abg-symtab-reader.h
index 43b40b79..390ee874 100644
--- a/src/abg-symtab-reader.h
+++ b/src/abg-symtab-reader.h
@@ -260,10 +260,10 @@  public:
   elf_symbol_sptr
   variable_symbol_is_exported(const GElf_Addr symbol_address);
 
-  bool
+  elf_symbol_sptr
   function_symbol_is_undefined(const string&);
 
-  bool
+  elf_symbol_sptr
   variable_symbol_is_undefined(const string&);
 
   static symtab_ptr
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 3e175209..5bf01528 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -2097,16 +2097,21 @@  test-abicompat/test6-var-changed-report-0.txt \
 test-abicompat/test6-var-changed-report-1.txt \
 test-abicompat/test6-var-changed-report-2.txt \
 test-abicompat/libtest7-fn-changed-libapp-v0.so \
+test-abicompat/libtest7-fn-changed-libapp-btf-v0.so \
 test-abicompat/libtest7-fn-changed-libapp-v1.so \
+test-abicompat/libtest7-fn-changed-libapp-btf-v1.so \
 test-abicompat/test7-fn-changed-app \
+test-abicompat/test7-fn-changed-app.btf \
 test-abicompat/test7-fn-changed-app.c \
 test-abicompat/test7-fn-changed-libapp-v0.c \
 test-abicompat/test7-fn-changed-libapp-v0.h \
 test-abicompat/test7-fn-changed-libapp-v1.c \
 test-abicompat/test7-fn-changed-libapp-v1.h \
 test-abicompat/test7-fn-changed-report-0.txt \
+test-abicompat/test7-fn-changed-report-0.1.txt \
 test-abicompat/test7-fn-changed-report-1.txt \
 test-abicompat/test7-fn-changed-report-2.txt \
+test-abicompat/test7-fn-changed-report-2.1.txt \
 test-abicompat/libtest8-fn-changed-libapp-v0.so \
 test-abicompat/libtest8-fn-changed-libapp-v1.so \
 test-abicompat/test8-fn-changed-app \
diff --git a/tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v0.so b/tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v0.so
new file mode 100755
index 0000000000000000000000000000000000000000..a61749662ff7d29cdfd9be39d5faf9cb95782909
GIT binary patch
literal 16560
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

literal 0
HcmV?d00001

diff --git a/tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so b/tests/data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so
diff --git a/tests/data/test-abicompat/test7-fn-changed-app.btf b/tests/data/test-abicompat/test7-fn-changed-app.btf
new file mode 100755
index 0000000000000000000000000000000000000000..71a01ef448a2a429a77fc9dfa2e7061da2931841
GIT binary patch
literal 17536
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

literal 0
HcmV?d00001

diff --git a/tests/data/test-abicompat/test7-fn-changed-app.c b/tests/data/test-abicompat/test7-fn-changed-app.c
--- a/tests/data/test-abicompat/test7-fn-changed-app.c
+++ b/tests/data/test-abicompat/test7-fn-changed-app.c
@@ -1,5 +1,7 @@ 
 // Compile this with:
 // gcc -g -o test7-fn-changed-app -L. -ltest7-fn-changed-libapp-v0 test7-fn-changed-app.c
+// Or, for BTF debug info, with:
+// gcc -gbtf -o test7-fn-changed-app.btf -L. -ltest7-fn-changed-libapp-v0 test7-fn-changed-app.c
 
 #include <stdio.h>
 #include "test7-fn-changed-libapp-v0.h"
diff --git a/tests/data/test-abicompat/test7-fn-changed-libapp-v0.c b/tests/data/test-abicompat/test7-fn-changed-libapp-v0.c
index 8c3581e2..c36993ce 100644
--- a/tests/data/test-abicompat/test7-fn-changed-libapp-v0.c
+++ b/tests/data/test-abicompat/test7-fn-changed-libapp-v0.c
@@ -1,5 +1,7 @@ 
 // Compile this with:
 // gcc -g -Wall -fPIC -shared -o libtest7-fn-changed-libapp-v0.so test7-fn-changed-libapp-v0.c
+// Or, for BTF debug info with:
+// gcc -gbtf -Wall -fPIC -shared -o libtest7-fn-changed-libapp-btf-v0.so test7-fn-changed-libapp-v0.c
 
 #include <stdio.h>
 #include "test7-fn-changed-libapp-v0.h"
diff --git a/tests/data/test-abicompat/test7-fn-changed-libapp-v1.c b/tests/data/test-abicompat/test7-fn-changed-libapp-v1.c
index 92c44394..822efa0c 100644
--- a/tests/data/test-abicompat/test7-fn-changed-libapp-v1.c
+++ b/tests/data/test-abicompat/test7-fn-changed-libapp-v1.c
@@ -1,5 +1,8 @@ 
 // Compile this with:
 // gcc -g -Wall -fPIC -shared -o libtest7-fn-changed-libapp-v1.so test7-fn-changed-libapp-v1.c
+// Or, for BTF debug info, with:
+// gcc -gbtf -Wall -fPIC -shared -o libtest7-fn-changed-libapp-btf-v1.so test7-fn-changed-libapp-v1.c
+
 #include <stdio.h>
 #include "test7-fn-changed-libapp-v1.h"
 
diff --git a/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt b/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
new file mode 100644
index 00000000..39b69d8f
--- /dev/null
+++ b/tests/data/test-abicompat/test7-fn-changed-report-0.1.txt
@@ -0,0 +1,19 @@ 
+ELF file 'test7-fn-changed-app.btf' might not be ABI compatible with 'libtest7-fn-changed-libapp-btf-v1.so' due to differences with 'libtest7-fn-changed-libapp-btf-v0.so' below:
+Functions changes summary: 0 Removed, 2 Changed, 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+2 functions with some indirect sub-type change:
+
+  [C] 'function float add(float, float)' has some indirect sub-type changes:
+    return type changed:
+      type name changed from 'float' to 'int'
+      type size hasn't changed
+      mangled name changed from 'float' to int
+
+  [C] 'function void print(const Student)' has some indirect sub-type changes:
+    parameter 1 of type 'const Student' has sub-type changes:
+      in unqualified underlying type 'struct Student':
+        type size changed from 128 to 192 (in bits)
+        1 data member insertion:
+          'float percentage', at offset 128 (in bits)
+
diff --git a/tests/data/test-abicompat/test7-fn-changed-report-2.1.txt b/tests/data/test-abicompat/test7-fn-changed-report-2.1.txt
new file mode 100644
index 00000000..4645006e
--- /dev/null
+++ b/tests/data/test-abicompat/test7-fn-changed-report-2.1.txt
@@ -0,0 +1,16 @@ 
+functions defined in library 'libtest7-fn-changed-libapp-btf-v1.so'
+have sub-types that are different from what application 'test7-fn-changed-app.btf' expects:
+
+  function float add(float, float):
+    return type changed:
+      type name changed from 'float' to 'int'
+      type size hasn't changed
+      mangled name changed from 'float' to int
+
+  function void print(const Student):
+    parameter 1 of type 'const Student' has sub-type changes:
+      in unqualified underlying type 'struct Student':
+        type size changed from 128 to 192 (in bits)
+        1 data member insertion:
+          'float percentage', at offset 128 (in bits)
+
diff --git a/tests/test-abicompat.cc b/tests/test-abicompat.cc
index e992454c..320436c3 100644
--- a/tests/test-abicompat.cc
+++ b/tests/test-abicompat.cc
@@ -168,6 +168,17 @@  InOutSpec in_out_specs[] =
     "data/test-abicompat/test7-fn-changed-report-0.txt",
     "output/test-abicompat/test7-fn-changed-report-0.txt",
   },
+#ifdef WITH_BTF
+  {
+    "data/test-abicompat/test7-fn-changed-app.btf",
+    "data/test-abicompat/libtest7-fn-changed-libapp-btf-v0.so",
+    "data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so",
+    "",
+    "--show-base-names --no-show-locs --no-redundant --btf",
+    "data/test-abicompat/test7-fn-changed-report-0.1.txt",
+    "output/test-abicompat/test7-fn-changed-report-0.1.txt",
+  },
+#endif
   {
     "data/test-abicompat/test7-fn-changed-app",
     "data/test-abicompat/libtest7-fn-changed-libapp-v1.so",
@@ -186,6 +197,17 @@  InOutSpec in_out_specs[] =
     "data/test-abicompat/test7-fn-changed-report-2.txt",
     "output/test-abicompat/test7-fn-changed-report-2.txt",
   },
+#ifdef WITH_BTF
+  {
+    "data/test-abicompat/test7-fn-changed-app.btf",
+    "data/test-abicompat/libtest7-fn-changed-libapp-btf-v1.so",
+    "",
+    "",
+    "--show-base-names --no-show-locs --weak-mode",
+    "data/test-abicompat/test7-fn-changed-report-2.1.txt",
+    "output/test-abicompat/test7-fn-changed-report-2.1.txt",
+  },
+#endif
   {
     "data/test-abicompat/test8-fn-changed-app",
     "data/test-abicompat/libtest8-fn-changed-libapp-v1.so",
diff --git a/tools/abicompat.cc b/tools/abicompat.cc
index 4e5a8e22..9c4771c9 100644
--- a/tools/abicompat.cc
+++ b/tools/abicompat.cc
@@ -34,6 +34,7 @@ 
 #include <iostream>
 #include <memory>
 #include <string>
+#include "config.h"
 #include "abg-config.h"
 #include "abg-tools-utils.h"
 #include "abg-corpus.h"
@@ -44,6 +45,9 @@ 
 #ifdef WITH_CTF
 #include "abg-ctf-reader.h"
 #endif
+#ifdef WITH_BTF
+#include "abg-btf-reader.h"
+#endif
 
 using std::string;
 using std::cerr;
@@ -111,6 +115,9 @@  public:
 #ifdef WITH_CTF
   bool			use_ctf;
 #endif
+#ifdef WITH_BTF
+  bool			use_btf;
+#endif
 
   options(const char* program_name)
     :prog_name(program_name),
@@ -128,6 +135,10 @@  public:
 #ifdef WITH_CTF
     ,
       use_ctf()
+#endif
+#ifdef WITH_BTF
+    ,
+      use_btf()
 #endif
   {}
 }; // end struct options
@@ -237,6 +248,9 @@  display_usage(const string& prog_name, ostream& out)
     "just one version of the library.\n"
 #ifdef WITH_CTF
     << "  --ctf use CTF instead of DWARF in ELF files\n"
+#endif
+#ifdef WITH_BTF
+    << "  --btf use BTF instead of DWARF in ELF files\n"
 #endif
     ;
 }
@@ -344,6 +358,10 @@  parse_command_line(int argc, char* argv[], options& opts)
 #ifdef WITH_CTF
       else if (!strcmp(argv[i], "--ctf"))
         opts.use_ctf = true;
+#endif
+#ifdef WITH_BTF
+      else if (!strcmp(argv[i], "--btf"))
+        opts.use_btf = true;
 #endif
       else
 	{