Let's say I have a program (program.c) that uses rand function in standard C library.
1 #include <stdlib.h>
2 int main(){
3 int rand_number = rand();
4 }
I also have a shared library (intercept.c) that I created to change the behaviour of rand function (simply adds +1 to the result) in the standard library.
int rand(void){
int (*rand_func)();
rand_func = dlsym(RTLD_NEXT, "rand");
int result = (*rand_func)();
return result + 1;
}
And I run the program with
LD_PRELOAD=./intercept.so ./program
Is there any way to get the line number (Line 3) and name of the caller function (main) without modifying the program.c's source code?
It is not immediate, but you can use backtrace() in order to obtain each frame in the call stack.
Then invoking the external command eu-addr2line -f -C -s --pretty-print -p your_pid the_previous_frames... (with popen() or pipe()/fork()/dup2()/exec()...) and parsing its output will provide the information you need
(if compiled with -g).
regarding:
Is there any way to get the line number (Line 3) and name of the caller function (main) without modifying the program.c's source code?
compile the program with the -ggdb3 option, Then set a break point where you want to stop the program. Then use the backtrace command bt. This will show the function names, the line numbers, etc
Another (Linux specific) approach is to compile everything with -g (perhaps also -O) using GCC and to use Ian Taylor's excellent libbacktrace.
That library parses the DWARF debug information and knows line numbers.
You'll need several hours to understand libbacktrace (read carefully the header file). I am using it in RefPerSys
My OS is ArchLinux, and write a simple program which just includes <uapi/linux/ptrace.h>:
#include <uapi/linux/ptrace.h>
void main(void) {}
The compilation complains:
test.c:1:10: fatal error: uapi/linux/ptrace.h: No such file or directory
#include <uapi/linux/ptrace.h>
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
I check /ust/include/uapi directory, and find it is empty. Finally, I find the correct uapi position is /usr/lib/modules/4.11.9-1-ARCH/build/include/uapi. So what is the canonical way of using <uapi/linux/..> in ArchLinux? Create a new link which points to /usr/lib/modules/4.11.9-1-ARCH/build/include/uapi or put the path into C_INCLUDE_PATH? They all seem a little weird.
TL;DR: pacman -S linux-api-headers and #include <linux/ptrace.h>
UAPI stands for User API and is the name of a folder in the kernel sources that is intended to be copied to an installation as part of the user-accessible kernel headers. In the case of Arch, some of these headers are copied to /usr/include/linux/ (plus some generated files on kernel compilation). But this is not part of the default install, it is actually separated in a different package: linux-api-headers (after installing, you can use #include <linux/ptrace.h>).
There is no /usr/include/uapi and this is by design, the contents of the original uapi folder are directly copied into /usr/include.
So, unless you are programming a kernel module, what you are probably looking for is #include <linux/ptrace.h>.
I am writing a FindXXX.cmake script for an external C library. I would like my script to provide information about the library version. However, the library only provides this information in the form of a function that returns the version number as a string.
I thought I could extract the version number by having FindXXX.cmake compile the following C program on the fly:
#include <stdio.h>
#include "library.h"
int main() {
char version[256];
get_version(version);
puts(version);
return 0;
}
In order for this to work, CMake should compile and run the program above at configure time, and use the information it prints as the version identifier. I know how to do the latter (execute_process), and I almost know how to do the former: CheckCSourceRuns comes to mind, but I do not know how to capture the stdout of the generated executable.
TL;DR: is there a way to compile a program, run it and capture its stdout from CMake at generation time?
You may use try_run for that purpose (it is assumed that your source file is named as foo_get_version.c):
try_run(foo_run_result foo_compile_result
foo_try_run ${CMAKE_CURRENT_LIST_DIR}/foo_get_version.c
RUN_OUTPUT_VARIABLE foo_run_output)
if(NOT foo_compile_result)
# ... Failed to compile
endif()
if(NOT foo_run_result EQUAL "0")
# ... Failed to run
endif()
# Now 'foo_run_output' variable contains output of your program.
Note, that try_run isn't executed when cross-compiling. Instead, CMake expects that the user will set cache variables foo_run_result and foo_run_result__TRYRUN_OUTPUT.
Is it possible to compile a C++ (or the like) program without generating the executable file but writing it and executing it directly from memory?
For example with GCC and clang, something that has a similar effect to:
c++ hello.cpp -o hello.x && ./hello.x $# && rm -f hello.x
In the command line.
But without the burden of writing an executable to disk to immediately load/rerun it.
(If possible, the procedure may not use disk space or at least not space in the current directory which might be read-only).
Possible? Not the way you seem to wish. The task has two parts:
1) How to get the binary into memory
When we specify /dev/stdout as output file in Linux we can then pipe into our program x0 that reads
an executable from stdin and executes it:
gcc -pipe YourFiles1.cpp YourFile2.cpp -o/dev/stdout -Wall | ./x0
In x0 we can just read from stdin until reaching the end of the file:
int main(int argc, const char ** argv)
{
const int stdin = 0;
size_t ntotal = 0;
char * buf = 0;
while(true)
{
/* increasing buffer size dynamically since we do not know how many bytes to read */
buf = (char*)realloc(buf, ntotal+4096*sizeof(char));
int nread = read(stdin, buf+ntotal, 4096);
if (nread<0) break;
ntotal += nread;
}
memexec(buf, ntotal, argv);
}
It would also be possible for x0 directly execute the compiler and read the output. This question has been answered here: Redirecting exec output to a buffer or file
Caveat: I just figured out that for some strange reason this does not work when I use pipe | but works when I use the x0 < foo.
Note: If you are willing to modify your compiler or you do JIT like LLVM, clang and other frameworks you could directly generate executable code. However for the rest of this discussion I assume you want to use an existing compiler.
Note: Execution via temporary file
Other programs such as UPX achieve a similar behavior by executing a temporary file, this is easier and more portable than the approach outlined below. On systems where /tmp is mapped to a RAM disk for example typical servers, the temporary file will be memory based anyway.
#include<cstring> // size_t
#include <fcntl.h>
#include <stdio.h> // perror
#include <stdlib.h> // mkostemp
#include <sys/stat.h> // O_WRONLY
#include <unistd.h> // read
int memexec(void * exe, size_t exe_size, const char * argv)
{
/* random temporary file name in /tmp */
char name[15] = "/tmp/fooXXXXXX";
/* creates temporary file, returns writeable file descriptor */
int fd_wr = mkostemp(name, O_WRONLY);
/* makes file executable and readonly */
chmod(name, S_IRUSR | S_IXUSR);
/* creates read-only file descriptor before deleting the file */
int fd_ro = open(name, O_RDONLY);
/* removes file from file system, kernel buffers content in memory until all fd closed */
unlink(name);
/* writes executable to file */
write(fd_wr, exe, exe_size);
/* fexecve will not work as long as there in a open writeable file descriptor */
close(fd_wr);
char *const newenviron[] = { NULL };
/* -fpermissive */
fexecve(fd_ro, argv, newenviron);
perror("failed");
}
Caveat: Error handling is left out for clarities sake. Includes for sake of brevity.
Note: By combining step main() and memexec() into a single function and using splice(2) for copying directly between stdin and fd_wr the program could be significantly optimized.
2) Execution directly from memory
One does not simply load and execute an ELF binary from memory. Some preparation, mostly related to dynamic linking, has to happen. There is a lot of material explaining the various steps of the ELF linking process and studying it makes me believe that theoretically possible. See for example this closely related question on SO however there seems not to exist a working solution.
Update UserModeExec seems to come very close.
Writing a working implementation would be very time consuming, and surely raise some interesting questions in its own right. I like to believe this is by design: for most applications it is strongly undesirable to (accidentially) execute its input data because it allows code injection.
What happens exactly when an ELF is executed? Normally the kernel receives a file name and then creates a process, loads and maps the different sections of the executable into memory, performs a lot of sanity checks and marks it as executable before passing control and a file name back to the run-time linker ld-linux.so (part of libc). The takes care of relocating functions, handling additional libraries, setting up global objects and jumping to the executables entry point. AIU this heavy lifting is done by dl_main() (implemented in libc/elf/rtld.c).
Even fexecve is implemented using a file in /proc and it is this need for a file name that leads us to reimplement parts of this linking process.
Libraries
UserModeExec
libelf -- read, modify, create ELF files
eresi -- play with elfes
OSKit (seems like a dead project though)
Reading
http://www.linuxjournal.com/article/1060?page=0,0 -- introduction
http://wiki.osdev.org/ELF -- good overview
http://s.eresi-project.org/inc/articles/elf-rtld.txt -- more detailed Linux-specific explanation
http://www.codeproject.com/Articles/33340/Code-Injection-into-Running-Linux-Application -- how to get to hello world
http://www.acsu.buffalo.edu/~charngda/elf.html -- nice reference of ELF structure
Loaders and Linkers by John Levine -- deeoer explanation of linking
Related Questions at SO
Linux user-space ELF loader
ELF Dynamic loader symbol lookup ordering
load-time ELF relocation
How do global variables get initialized by the elf loader
So it seems possible, you decide whether is also practical.
Yes, though doing it properly requires designing significant parts of the compiler with this in mind. The LLVM guys have done this, first with a kinda-separate JIT, and later with the MC subproject. I don't think there's a ready-made tool doing it. But in principle, it's just a matter of linking to clang and llvm, passing the source to clang, and passing the IR it creates to MCJIT. Maybe a demo does this (I vaguely recall a basic C interpreter that worked like this, though I think it was based on the legacy JIT).
Edit: Found the demo I recalled. Also, there's cling, which seems to do basically what I described, but better.
Linux can create virtual file systems in RAM using tempfs. For example, I have my tmp directory set up in my file system table like so:
tmpfs /tmp tmpfs nodev,nosuid 0 0
Using this, any files I put in /tmp are stored in my RAM.
Windows doesn't seem to have any "official" way of doing this, but has many third-party options.
Without this "RAM disk" concept, you would likely have to heavily modify a compiler and linker to operate completely in memory.
If you are not specifically tied to C++, you may also consider other JIT based solutions:
in Common Lisp SBCL is able to generate machine code on the fly
you could use TinyCC and its libtcc.a which emits quickly poor (i.e. unoptimized) machine code from C code in memory.
consider also any JITing library, e.g. libjit, GNU Lightning, LLVM, GCCJIT, asmjit
of course emitting C++ code on some tmpfs and compiling it...
But if you want good machine code, you'll need it to be optimized, and that is not fast (so the time to write to a filesystem is negligible).
If you are tied to C++ generated code, you need a good C++ optimizing compiler (e.g. g++ or clang++); they take significant time to compile C++ code to optimized binary, so you should generate to some file foo.cc (perhaps in a RAM file system like some tmpfs, but that would give a minor gain, since most of the time is spent inside g++ or clang++ optimization passes, not reading from disk), then compile that foo.cc to foo.so (using perhaps make, or at least forking g++ -Wall -shared -O2 foo.cc -o foo.so, perhaps with additional libraries). At last have your main program dlopen that generated foo.so. FWIW, MELT was doing exactly that, and on Linux workstation the manydl.c program shows that a process can generate then dlopen(3) many hundred thousands of temporary plugins, each one being obtained by generating a temporary C file and compiling it. For C++ read the C++ dlopen mini HOWTO.
Alternatively, generate a self-contained source program foobar.cc, compile it to an executable foobarbin e.g. with g++ -O2 foobar.cc -o foobarbin and execute with execve that foobarbin executable binary
When generating C++ code, you may want to avoid generating tiny C++ source files (e.g. a dozen lines only; if possible, generate C++ files of a few hundred lines at least; unless lots of template expansion happens thru extensive use of existing C++ containers, where generating a small C++ function combining them makes sense). For instance, try if possible to put several generated C++ functions in the same generated C++ file (but avoid having very big generated C++ functions, e.g. 10KLOC in a single function; they take a lot of time to be compiled by GCC). You could consider, if relevant, to have only one single #include in that generated C++ file, and pre-compile that commonly included header.
Jacques Pitrat's book Artificial Beings, the conscience of a conscious machine (ISBN 9781848211018) explains in details why generating code at runtime is useful (in symbolic artificial intelligence systems like his CAIA system). The RefPerSys project is trying to follow that idea and generate some C++ code (and hopefully, more and more of it) at runtime. Partial evaluation is a relevant concept.
Your software is likely to spend more CPU time in generating C++ code than GCC in compiling it.
tcc compiler "-run" option allows for exactly this, compile into memory, run there and finally discard the compiled stuff. No filesystem space needed. "tcc -run" can be used in shebang to allow for C script, from tcc man page:
#!/usr/local/bin/tcc -run
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
C scripts allow for mixed bash/C scripts, with "tcc -run" not needing any temporary space:
#!/bin/bash
echo "foo"
sed -n "/^\/\*\*$/,\$p" $0 | tcc -run -
exit
/**
*/
#include <stdio.h>
int main()
{
printf("bar\n");
return 0;
}
Execution output:
$ ./shtcc2
foo
bar
$
C scripts with gcc are possible as well, but need temporary space like others mentioned to store executable. This script produces same output as the previous one:
#!/bin/bash
exc=/tmp/`basename $0`
if [ $0 -nt $exc ]; then sed -n "/^\/\*\*$/,\$p" $0 | gcc -x c - -o $exc; fi
echo "foo"
$exc
exit
/**
*/
#include <stdio.h>
int main()
{
printf("bar\n");
return 0;
}
C scripts with suffix ".c" are nice, headtail.c was my first ".c" file that needed to be executable:
$ echo -e "1\n2\n3\n4\n5\n6\n7" | ./headtail.c
1
2
3
6
7
$
I like C scripts, because you just have one file, you can easily move around, and changes in bash or C part require no further action, they just work on next execution.
P.S:
The above shown "tcc -run" C script has a problem, C script stdin is not available for executed C code. Reason was that I passed extracted C code via pipe to "tcc -run". New gist run_from_memory_stdin.c does it correctly:
...
echo "foo"
tcc -run <(sed -n "/^\/\*\*$/,\$p" $0) 42
...
"foo" is printed by bash part, "bar 42" from C part (42 is passed argv[1]), and piped script input gets printed from C code then:
$ route -n | ./run_from_memory_stdin.c
foo
bar 42
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.29.58.98 0.0.0.0 UG 306 0 0 wlan1
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
169.254.0.0 0.0.0.0 255.255.0.0 U 303 0 0 wlan0
172.29.58.96 0.0.0.0 255.255.255.252 U 306 0 0 wlan1
$
One can easily modify the compiler itself. It sounds hard first but thinking about it, it seams obvious. So modifying the compiler sources directly expose a library and make it a shared library should not take that much of afford (depending on the actual implementation).
Just replace every file access with a solution of a memory mapped file.
It is something I am about to do with compiling something transparently in the background to op codes and execute those from within Java.
-
But thinking about your original question it seams you want to speed up compilation and your edit and run cycle. First of all get a SSD-Disk you get almost memory speed (use a PCI version) and lets say its C we are talking about. C does this linking step resulting in very complex operations that are likely to take more time than reading and writing from / to disk. So just put everything on SSD and live with the lag.
Finally the answer to OP question is yes!
I found memrun repo from guitmz, that demoed running (x86_64) ELF from memory, with golang and assembler. I forked that, and provided C version of memrun, that runs ELF binaries (verified on x86_64 and armv7l), either from standard input, or via first argument process substitution. The repo contains demos and documentation (memrun.c is 47 lines of code only):
https://github.com/Hermann-SW/memrun/tree/master/C#memrun
Here is simplest example, with "-o /dev/fd/1" gcc compiled ELF gets sent to stdout, and piped to memrun, which executes it:
pi#raspberrypi400:~/memrun/C $ gcc info.c -o /dev/fd/1 | ./memrun
My process ID : 20043
argv[0] : ./memrun
no argv[1]
evecve --> /usr/bin/ls -l /proc/20043/fd
total 0
lr-x------ 1 pi pi 64 Sep 18 22:27 0 -> 'pipe:[1601148]'
lrwx------ 1 pi pi 64 Sep 18 22:27 1 -> /dev/pts/4
lrwx------ 1 pi pi 64 Sep 18 22:27 2 -> /dev/pts/4
lr-x------ 1 pi pi 64 Sep 18 22:27 3 -> /proc/20043/fd
pi#raspberrypi400:~/memrun/C $
The reason I was interested in this topic was usage in "C script"s. run_from_memory_stdin.c demonstrates all together:
pi#raspberrypi400:~/memrun/C $ wc memrun.c | ./run_from_memory_stdin.c
foo
bar 42
47 141 1005 memrun.c
pi#raspberrypi400:~/memrun/C $
The C script producing shown output is so small ...
#!/bin/bash
echo "foo"
./memrun <(gcc -o /dev/fd/1 -x c <(sed -n "/^\/\*\*$/,\$p" $0)) 42
exit
/**
*/
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("bar %s\n", argc>1 ? argv[1] : "(undef)");
for(int c=getchar(); EOF!=c; c=getchar()) { putchar(c); }
return 0;
}
P.S:
I added tcc's "-run" option to gcc and g++, for details see:
https://github.com/Hermann-SW/memrun/tree/master/C#adding-tcc--run-option-to-gcc-and-g
Just nice, and nothing gets stored in filesystem:
pi#raspberrypi400:~/memrun/C $ uname -a | g++ -O3 -Wall -run demo.cpp 42
bar 42
Linux raspberrypi400 5.10.60-v7l+ #1449 SMP Wed Aug 25 15:00:44 BST 2021 armv7l GNU/Linux
pi#raspberrypi400:~/memrun/C $
Looking into learning C. As I understand it when I say #include <stdio.h> it grabs stdio.h from the default location...usually a directory inside your working directory called include. How do I actually get the file stdio.h? Do I need to download a bunch of .h files and move them from project to project inside the include directory? I did the following in a test.c file. I then ran make test and it outputted a binary. When I ran ./test I did not see hello print onto my screen. I thought I wasn't seeing output maybe because it doesn't find the stdio.h library. But then again if I remove the greater than or less than signs in stdio the compiler gives me an error. Any ideas?
I'm on a Mac running this from the command line. I am using: GNU Make 3.81. This program built for i386-apple-darwin10.0
#include <stdio.h>
main()
{
printf("hello");
}
Edit: I have updated my code to include a datatype for the main function and to return 0. I still get the same result...compiles without error and when I run the file ./test it doesn't print anything on screen.
#include <stdio.h>
int main()
{
printf("hello");
return 0;
}
Update:
If I add a \n inside of the printf it works! so this will work:
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
Your code should have preferably
printf("hello\n");
or
puts("hello");
If you want to know where does the standard header file <stdio.h> comes from, you could run your compiler with appropriate flags. If it is gcc, try compiling with
gcc -H -v -Wall hello.c -o hello
Pedantically, a standard header file is even not required to exist as a file; the standard permits an implementation which would process the #include <stdio.h> without accessing the file system (but e.g. by retrieving internal resources inside the compiler, or from a database...). Few compilers behave that way, most really access something in the file system.
If you didn't have the file, you'd get a compilation error.
My guess is the text was printed, but the console closed before you got the chance to see it.
Also, main returns an int, and you should return 0; to signal successful completion.
#include <header.h>, with angle brackets, searches in standard system locations, known to the compiler-- not in your project's subdirectories. In Unix systems (including your Mac, I believe), stdio.h is typically in /usr/include. If you use #include "header.h", you're searching subdirectories first and then the same places as with <header.h>.
But you don't need to find or copy the header to run your program. It is read at compilation time, so your ./test doesn't need it at all. Your program looks like it should have worked. Is it possible that you just typed "test", not "./test", and got the system command "test"? (Suggestion: Don't name your programs "test".)
Just going to leave this here : STILL! in 2018, December... Linux Mint 18.3
has no support for C development.
innocent / # cc ThoseSorts.c
ThoseSorts.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
innocent / # gcc ThoseSorts.c
ThoseSorts.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
innocent / # apt show libc6
(Abbreviated)::
Package: libc6
Version: 2.23-0ubuntu10
Priority: required
Section: libs
Source: glibc
Origin: Ubuntu
Installed-Size: 11.2 MB
Depends: libgcc1
Homepage: http://www.gnu.org/software/libc/libc.html
Description: GNU C Library: Shared libraries
Contains the standard libraries that are used by nearly all programs on
the system. This package includes shared versions of the standard C library
and the standard math library, as well as many others.
innocent / # apt-get install libc6-dev libc-dev
So, magic... and a minute later they are all installed on the
computer and then things work as they should.
Not all distros bundle up all the C support libs in each ISO.
Hunh.
hardlyinnocent / # gcc ThoseSorts.c
hardlyinnocent / # ./a.out
20
18
17
16
... ... ...