ThoughtGang / opdis

libopcodes-based disassembler
GNU General Public License v2.0
35 stars 10 forks source link

Build failure on POWER Linux #11

Closed PerMildner closed 8 years ago

PerMildner commented 8 years ago

Building on POWER fails with:

dist/.libs/libopdis.so: undefined reference to `print_insn_i386_intel'
dist/.libs/libopdis.so: undefined reference to `print_insn_i386_att'
collect2: error: ld returned 1 exit status
$ uname -a
Linux XXX 3.10.0-229.4.2.ael7b.ppc64le #1 SMP Fri Apr 24 15:23:58 EDT 2015 ppc64le ppc64le ppc64le GNU/Linux

$ cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ 
mkfs commented 8 years ago

Yeah, opdis has only been built for x86(-64). I had some plans to do a multi-arch release (via binutils-mgr), but had too much other stuff to do.

PerMildner commented 8 years ago

I got it to run, by ifdeffing out all the x86-specific things and letting the client do an explicit call to opdis_set_arch() after opdis_init().

It would be easy enough to have configure detect (or relying on pre-defined preprocessor symbols) whether it is running on an x86 platform and prevent opdis from linking in x86-specific things when it is running on a non-x86 platform.

Such a change would give basic support for opdis on all binutils platforms, which would be nice.

Using binutils-mgr seems to be overkill for simple non-cross-disassembler applications.

mkfs commented 8 years ago

It's not that straightforward. GNU libopcodes has a really bad design. The "disassemble instruction" function is named "printinsn$ARCH", so in autoconf you'd need to map the detected platform to the binutils architecture name, then use pre-processor symbols to determine what print_insn function gets used at compile-time. Easy enough, sure, but tedious and time-consuming.

Once that is done, you'll find that there is no metadata for non-x86 instructions, because this is implemented manually inside of opdis. Without the instruction metadata, stuff like control-flow disassembly won't work. Adding instruction metadata is a LOT of tedious work, which is why I never bothered adding architectures beyond x86.

PerMildner commented 8 years ago

I did the straightforward thing, selecting UNKNOWN architecture unless the compile-time platform is x86. This is good enough since the user of OPDIS can then do the correct thing by calling opdis_set_arch() after opdis_init().

Of course it does not get the fancy things that need metadata but it does get the basic disassembler functionality which makes OPDIS at least somewhat useful on all platforms out-of-the-box. This basic functionality is enough for my application.

mkfs commented 8 years ago

Ah, you mean the user supplies the print_insn function. A bit ugly, as it requires the user knowing the function to pass (unless the BFD provides it? I forget), with no default unless there is a huge switch statement in autoconf to map platform to binutils arch+mach.

I could wrap all of the x86 stuff in macros so that it doesn't appear when on non-x86 architectures, forcing the user to supply the print-insn function on all architectures. Maybe next time I'm the better way through a bottle of scotch, and therefore willing to deal with binutils against my normally-unimpaired judgement.