In gdb I can use call
to run functions,but what if I want to run some additional assembly?
2 Answers
Prior to GCC 5 (1), I don't know of a way to run arbitrary machine code unless you actually enter the machine code into memory and then run it.
If you want to run code that's already in memory, you can just set the instruction pointer to the start, a breakpoint at the end, then go. Then, after the breakpoint, change the instruction pointer back to its original value.
But I can't actually see the use case for this. That doesn't mean there isn't one, just that anything you can do by running code, you can also achieve by directly modifying the registers, flags, memory and so forth.
For example, the command:
info registers
will dump the current values of the registers while:
set $eax = 42
will change the eax
register to 42
.
You can also change memory in this way:
set *((char*)0xb7ffeca0) = 4
This writes a single byte to memory location 0xb7ffeca0
and you can also use that same method to store wider data types.
(1) GCC 5 allows you to compile and execute arbitrary code with the compile code
command, as documented here.

- 854,327
- 234
- 1,573
- 1,953
-
How to modify registers if `mov` etc can't be run directly? – gdb Mar 30 '11 at 01:59
-
@gdb: You can use `set $eax = 42`, for example. See the update. – paxdiablo Mar 30 '11 at 02:13
-
Can you also demonstrate how to change memory with `set`? – gdb Mar 30 '11 at 02:22
-
There is a cases for executing a particular assembly instructions in a memory. It could be a multimedia commands, which result might be not easy to calculate. Or a few usual commands which easier to execute, than to edit a registers/memory by hand, with a probability to make an error. – Hi-Angel Jun 04 '14 at 09:39
-
It would be fun to make a Python API command that does it. Find some free executable memory, compile, write commands there, change ESP to it, set last command to jump back. Likely hard :-) – Ciro Santilli OurBigBook.com Jul 10 '15 at 12:25
-
`compile code` was recently added to GDB and allows "arbitrary" compilation: http://stackoverflow.com/a/31709579/895245 – Ciro Santilli OurBigBook.com Jul 29 '15 at 19:36
compile code
command
Introduced around 7.9, it allows code compilation and injection, documentation: https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html
main.c
#include <stdio.h>
int main(void) {
int i = 0;
printf("%d\n", i);
return 0;
}
Compile and run:
gcc -ggdb3 -o main.out main.c
gdb main.out
Then in GDB:
(gdb) start
Temporary breakpoint 1 at 0x113d: file main.c, line 4.
Starting program: /home/ciro/test/main.out
Temporary breakpoint 1, main () at main.c:4
4 int i = 0;
(gdb) next
5 printf("%d\n", i);
(gdb) compile code int j = 1; i = j; asm("nop");
(gdb) continue
Continuing.
1
[Inferior 1 (process 30256) exited normally]
Program output:
1
For this to work in GDB 7.9.1, GCC 5.1 I had to run GDB with:
LD_LIBRARY_PATH="$(dirname "$(gcc -print-libgcc-file-name)"):$LD_LIBRARY_PATH" gdb main.out
so that libcc1.so
will be visible: that is a recent GCC component that exposes a C API to the cc1
compiler, but this was not needed anymore on Ubuntu 19.04. This was still required for C++ however on a minimal:
main.cpp
#include <iostream>
int main() {
int i = 0;
std::cout << i << std::endl;
}
and:
compile code int j = 1; i = j; asm("nop");
There are a few constructs that did not work as I expected:
includes such as:
compile code printf('asdf\n')
in Ubuntu 19.04.
On main.c above,
printf
without include worked because we already included it in the source, but if I try it on an emptymain()
without the include it fails with:gdb command line:1:1: warning: incompatible implicit declaration of built-in function ‘printf’ gdb command line:1:1: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’ gdb command line:1:8: warning: character constant too long for its type gdb command line:1:8: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion] gdb command line:1:8: note: expected ‘const char *’ but argument is of type ‘int’ gdb command line:1:1: warning: format not a string literal and no format arguments [-Wformat-security]
In C++ Ubuntu 19.04:
compile code std::cout << "Hello world\n";
failed with:
*** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins. Event | Plugins PLUGIN_PRE_GENERICIZE | libcp1plugin PLUGIN_GGC_MARKING | libcp1plugin PLUGIN_PRAGMAS | libcp1plugin gdb command line:1:6: internal compiler error: in plugin_build_decl, at libcc1/libcp1plugin.cc:1059 Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions. Compilation failed.
See also: How to compile C++ code in GDB?

- 347,512
- 102
- 1,199
- 985
-
1This doesn't seem to actually work for something like `asm volatile ("mov $abc, %eax")`, when the language is C. After the `compile` command returns, `$rax` still has its original value. GDB 7.10 doesn't support the `compile` command when the source language is asm, so this doesn't work even when debugging a function written in asm. – Peter Cordes Feb 17 '16 at 04:42
-
@PeterCordes thanks, I hadn't tried that out. `compile` is really quite limited. But there is potential. – Ciro Santilli OurBigBook.com Feb 17 '16 at 10:22
-
Yeah it looks really handy for C/C++, but not for just experimenting with what instructions do with different inputs. I guess you could use a C variable as an output operand, but then you need an instruction to use it. At that point it's probably easier to just put instructions in a file, assemble/link it, and single-step that. Thanks for pointing it out, even though it's not a good answer to *this* question. >. – Peter Cordes Feb 17 '16 at 10:28
-
Your example with `std::cout` can be rewritten with `-raw` argument as `compile code -raw #include
^Mvoid _gdb_expr() { std::cout << "Hello\n"; }` (replace `^M` here with Ctrl-V, Enter) This does work for me. – Ruslan Sep 16 '19 at 13:19 -
@Ruslan thanks for clarifying what `-raw` does! Unfortunately I couldn't get it to work on Ubuntu 19.04 :-( A C++ hello world fails with `‘cout’ is not a member of ‘std’`, and an empty `main` fails with `warning: Could not find symbol "_ZSt4cout" for compiled module "/tmp/gdbobj-dxRNbH/out1.o".` when I tried. – Ciro Santilli OurBigBook.com Sep 16 '19 at 13:34
-
`‘cout’ is not a member of ‘std’` means you've failed to `#include
` in your `compile` command. The linker error happens to me when the app hadn't included ` – Ruslan Sep 16 '19 at 13:50` by itself, this I'm not sure how to fix from within GDB. For reference, see the full working bash/gdb session [here](https://pastebin.com/raw/TWyZ6vtn).