samunders-core / le_disasm

libopcodes-based (AT&T syntax) linear executable (MZ/LE/LX DOS EXEs) disassembler modified from http://swars.vexillium.org/files/swdisasm-1.0.tar.bz2
GNU General Public License v3.0
19 stars 5 forks source link

Compilation error under Arch Linux #2

Closed ghost closed 5 years ago

ghost commented 5 years ago

Hello,

Compiling le_disasm under Arch Linux produces the following error:

In file included from /usr/local/include/dis-asm.h:35,
                 from dis_info.h:4,
                 from analyzer.h:13,
                 from print.h:4,
                 from main.cpp:3:
/usr/local/include/bfd.h:35:2: error: #error config.h must be included before this header
 #error config.h must be included before this header
  ^~~~~
In file included from dis_info.h:4,
                 from analyzer.h:13,
                 from print.h:4,
                 from main.cpp:3:
/usr/local/include/dis-asm.h: In function ‘const char* next_disassembler_option(const char*)’:
/usr/local/include/dis-asm.h:298:21: error: ‘strchr’ was not declared in this scope
   const char *opt = strchr (options, ',');
                     ^~~~~~
/usr/local/include/dis-asm.h:298:21: note: ‘strchr’ is defined in header ‘<cstring>’; did you forget to ‘#include <cstring>’?
/usr/local/include/dis-asm.h:36:1:
+#include <cstring>

/usr/local/include/dis-asm.h:298:21:
   const char *opt = strchr (options, ',');
                     ^~~~~~
In file included from analyzer.h:13,
                 from print.h:4,
                 from main.cpp:3:
dis_info.h: In member function ‘void DisInfo::disassemble(uint32_t, const void*, size_t, Insn&)’:
dis_info.h:26:14: error: ‘print_insn_i386_att’ was not declared in this scope
   int size = print_insn_i386_att(addr, this);
              ^~~~~~~~~~~~~~~~~~~
dis_info.h:26:14: note: suggested alternative: ‘print_insn_rl78_g14’
   int size = print_insn_i386_att(addr, this);
              ^~~~~~~~~~~~~~~~~~~
              print_insn_rl78_g14

This can be silenced by adding the following lines into main.cpp:

#include <cstring>
#define PACKAGE

and this line in dis_info.h:

int print_insn_i386_att (bfd_vma pc, disassemble_info *info);

However, linkage does fail with the following error:

/usr/local/bin/ld: ./main.o: in function `DisInfo::disassemble(unsigned int, void const*, unsigned long, Insn&)':
/home/marespiaut/code/le_disasm/dis_info.h:28: undefined reference to `print_insn_i386_att(unsigned long, disassemble_info*)'
collect2: error: ld returned 1 exit status

I've tried fixing it with no success.

I wonder if print_insn_i386_att can be replaced by something else, as the source code of GNU binutils says that this function is here “for backwards compatibility only”:

/* Here for backwards compatibility.  When gdb stops using
   print_insn_i386_att and print_insn_i386_intel these functions can
   disappear, and print_insn_i386 be merged into print_insn.  */
int
print_insn_i386_att (bfd_vma pc, disassemble_info *info)
{
  intel_syntax = 0;

  return print_insn (pc, info);
}

Best regards.

samunders-core commented 5 years ago

Hi. My interpretation of above is that Arch is not packaging binutils-gdb, which contains disassembling functions. Of course print_insn_i386_att can be replaced, do you have something specific in mind? Please note that output of print_insn_i386_att is string-matched to workaround libopcodes bugs, so I assume creating new AUR package with complete binutils would be easier (not that I ever done such thing). Is building on Arch hard requirement? My build succeeded on Linux Mint/Ubuntu/Debian.

ghost commented 5 years ago

Hello,

binutils is indeed compiled with the flag --disable-gdb, as stated in its PKGBUILD.

However, re-compiling binutils without this flag under Arch Linux doesn't solve the issue, and produces exactly all the same problems.

Using this software under a Debian-based Linux distribution would require me to have a VM, but my computer is too limited for that.

samunders-core commented 5 years ago

When you recompile binutils with gdb support, do you install it? What does grep -r print_insn_i386 /usr 2>/dev/null print? (Output on Ubuntu: Binary file /usr/lib/x86_64-linux-gnu/libopcodes-2.30-system.so matches, because since then I reinstalled, still without development files) Also linked PKGBUILD ends with

  # No shared linking to these files outside binutils
  rm -f "$pkgdir"/usr/lib/lib{bfd,opcodes}.so
  echo 'INPUT( /usr/lib/libbfd.a -liberty -lz -ldl )' > "$pkgdir/usr/lib/libbfd.so"
  echo 'INPUT( /usr/lib/libopcodes.a -lbfd )' > "$pkgdir/usr/lib/libopcodes.so"

which are used at linking by g++ -o "output.bin" ./main.o -lstdc++ -lopcodes -lbfd -rdynamic

ghost commented 5 years ago

Doing grep -r print_insn_i386 /usr/lib 2>/dev/null returns the following:

Binary file /usr/lib/libopcodes.a matches
Binary file /usr/lib/libopcodes-2.32.so matches

However, I have commented out the lines you have mentionned in the PKGBUILD, and recompiled the package.

Now, launching g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.o" -o "main.o" "main.cpp" doesn't return any errors, but launching g++ -o "le_disasm" ./main.o -lstdc++ -lopcodes -lbfd -rdynamic returns the following one:

/usr/bin/ld: ./main.o: in function `DisInfo::disassemble(unsigned int, void const*, unsigned long, Insn&)':
/home/marespiaut/code/le_disasm/dis_info.h:28: undefined reference to `print_insn_i386_att(unsigned long, disassemble_info*)'
collect2: error: ld returned 1 exit status
samunders-core commented 5 years ago

It appears your build of binutils is fine. What's your output of strings /usr/lib/libopcodes-2.32.so | sort | uniq | grep print? Mine:

# strings /usr/lib/x86_64-linux-gnu/libopcodes-2.30-system.so | sort | uniq | grep print
__fprintf_chk
generic_print_address
print_i386_disassembler_options
print_insn_i386
print_insn_i386_att
print_insn_i386_intel
__sprintf_chk
neuromancer commented 5 years ago

I'm having a similar issue as @marespiaut and the strings output is the same as @samunders-core:

$ strings /usr/lib/libopcodes-2.32.so | sort | uniq | grep print
__fprintf_chk
generic_print_address
print_i386_disassembler_options
print_insn_i386
print_insn_i386_att
print_insn_i386_intel
__sprintf_chk
samunders-core commented 5 years ago

@neuromancer Just to be sure I get it right: you also want/need to build it on Arch Linux? Output you posted looks fine, could you post gcc command line you're trying and error you're getting?

neuromancer commented 5 years ago

Yes, I'm using ArchLinux as well (but there is a similar issue in Ubuntu 18.04). I recompiled and re-installed the binutils package without the --disable-gdb flag. Also, I did some small changes:

$ git diff
diff --git a/dis_info.h b/dis_info.h
index 2ea4411..96215d0 100644
--- a/dis_info.h
+++ b/dis_info.h
@@ -2,7 +2,7 @@
 #define SRC_DIS_INFO_H_

 #include <dis-asm.h>
-
+extern int print_insn_i386_att (bfd_vma pc, disassemble_info *info);
 #include "insn.h"

 class DisInfo : disassemble_info {
diff --git a/main.cpp b/main.cpp
index 558cf0d..0119c5d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,5 +1,8 @@
 #include <fstream>

+#include <cstring>
+#define PACKAGE
+
 #include "print.h"

 int main(int argc, char **argv) {

Compilation works, but linking fails:

$ g++  -o "le_disasm"  ./main.o   -lstdc++ -lopcodes -lbfd -rdynamic
/usr/bin/ld: ./main.o: in function `DisInfo::disassemble(unsigned int, void const*, unsigned long, Insn&)':
/home/g/Code/le_disasm/dis_info.h:26: undefined reference to `print_insn_i386_att(unsigned long, disassemble_info*)'
collect2: error: ld returned 1 exit status
samunders-core commented 5 years ago

Thanks @neuromancer, you almost had it. extern "C" ... does the trick, I've updated master with your patch and now it builds+links on Ubuntu 18.04. I assume after binutils is built without --disable-gdb le_disasm will build on Arch as well.

neuromancer commented 5 years ago

It works! Thanks a lot @samunders-core