GDB JIT Interface simpliest example
Asked Answered
I

3

11

I read the JIT Interface chapter and faced the problem: how to write a simpliest example for simpliest possible code (preferably in C++ and at least for x86-64 platform)? Say, I want to debug the following code (namely, code_.data() function):

#include "eallocator.hpp"

#include <iostream>
#include <vector>

#include <cstdlib>

int main()
{
    std::vector< std::uint8_t, eallocator< std::uint8_t > > code_;
    code_.push_back(0b11011001u); code_.push_back(0b11101011u); // fldpi
    code_.push_back(0b11000011u);                               // ret

    double result_;
    __asm("call *%1"
            : "=&t"(result_)
            : "r"(code_.data())
            :
              );
    std::cout << result_ << std::endl;

    return EXIT_SUCCESS;
}

What (minimally) I should to do to use the interface? Particularly, I want to be able to provide some pseudocode (arbitrary text in memory) as "source" (with corresponding lines info) if it possible.

How to instrument the above code (or something similar), while remaining terse.

#include "eallocator.hpp" should use the approaches from this for Windows or from this for Linux.

Inherent answered 18/11, 2013 at 11:44 Comment(1)
-450 for bounty. So sorry, but I cannot offer anything else.Inherent
D
4

If I understand you correctly, what you're trying to do is to dynamically emit some executable code into memory and set up GDB to be able to debug it, is that correct?

What makes this task quite difficult to express in a "minimal" example is that GDB actually expects to find a whole ELF object in memory, not just a lump of code. GDB's registration interfaces need ELF symbol tables to examine in order to figure out which symbols exist in the emitted code and where they reside.

Your best bet to do this without unreasonable effort is to look at LLVM. The Debugging JIT-ed Code with GDB section in the documentation describes how to do this with MCJIT, with a full example at the bottom - going from some simple C code, JITing it to memory with LLVM MCJIT and attaching GDB to it. Moreover, since the LLVM MCJIT framework is involved you get full debug info there, up to the C level!

To be honest, that documentation section has not been updated in a while, but it should work. Let me know if it doesn't - I'll look into fixing things and updating it.

I hope this helps.

Decomposer answered 19/12, 2013 at 14:26 Comment(2)
Your assumption is right. But how MinGW and GDB works in Windows? There is no ELF file format, only PE.Inherent
@Dukales: AFAIK, MinGW indeed emits PE on Windows, but for debugging it actually embeds DWARF into it. GDB on Windows reads PE too, but then slurps the DWARF debug info from it.Decomposer
G
1

There is an example in their tests which should help

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/testsuite/gdb.base/jit-main.c

Galla answered 25/11, 2013 at 21:49 Comment(0)
L
1

Eli's answer is 100% correct. You need to give GDB a complete, valid ELF object, and if you don't, it will complain with a generic error or abort/segfault (or do nothing and ignore your symbols...). That said, I created a "minimal" working example:

https://gist.github.com/yyny/4a012029b5889853c18b1efc19bb598e

Note that this example is for Unix (SYSV) systems on x86-64.

Latria answered 30/7 at 20:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.