Can you directly call functions in command line? - c

For example, if I have the following function
void printText(char text [100]){
printf("%d", text);
}
could I then do this in the command line
printText(Hello World)
and then get my expected output as
Hello World

It depends on your shell. Some shells do support functions. In bash, the POSIX shell, and probably others, the following is the correct syntax:
printText() {
printf '%s\n' "$1"
}
printText 'Hello World'
If you meant your question literally, then no, it's not possible to call a function without even mentioning the file in which it's located. The language used to write the function is irrelevant.
But it is possible to compile a C function and have it called from the shell somehow? Yes. If you created a shared library (shared object on unixy systems or DLL on Windows) from the function, you could. It would require a tool to do so, but such a tool could exit. (Windows also supports COM objects and a number of derived techs. Some of these might even make the task easier.)
(I can't tell if such tools actually do exist or what they are because software recommendations are off-topic on StackOverflow. I will say that such a tool could be built around a library such as libffi.)

One solution would be to rely on dlopen()/LoadLibrary() and
dlsym()/GetProcAddress() but you cannot ensure the function
prototype conforms to your expectation.
A more robust solution consists in providing a lookup table filled
with functions that you know are compliant with the intended usage.
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
$ ./prog_c printText "Hello world"
printText --> <Hello world>
$ ./prog_c textLen "Hello world"
textLen --> 11
$ ./prog_c what "Hello world"
cannot find function 'what'
**/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
void
printText(const char *text)
{
printf("printText --> <%s>\n", text);
}
void
textLen(const char *text)
{
printf("textLen --> %d\n", (int)strlen(text));
}
typedef struct
{
const char *name;
void (*fnct)(const char *);
} TextFunction;
bool // success
call_text_function(const char *name,
const char *arg)
{
static TextFunction table[]={ {"printText", printText},
{"textLen", textLen},
{NULL, NULL} };
for(int i=0; table[i].name!=NULL; ++i)
{
if(strcmp(table[i].name, name)==0)
{
table[i].fnct(arg);
return true;
}
}
return false;
}
int
main(int argc,
char **argv)
{
if(argc!=3)
{
fprintf(stderr, "usage: %s function arg\n", argv[0]);
return 1;
}
if(!call_text_function(argv[1], argv[2]))
{
fprintf(stderr, "cannot find function '%s'\n", argv[1]);
return 1;
}
return 0;
}

Related

With MACH-O is there a way to register a function that will run before main?

Under Linux, I can register a routine that will run before main. For example:
#include <stdio.h>
void myinit(int argc, char **argv, char **envp) {
printf("%s: %s\n", __FILE__, __FUNCTION__);
}
__attribute__((section(".init_array"))) typeof(myinit) *__init = myinit;
By compiling this with GCC and linking it in, the function myinit will be run before main.
Is there way to do this under Mac OSX and MACH-O?
Thanks.
You could place the function in __mod_init_func data section of Mach-O binary.
From Mach-O format reference:
__DATA,__mod_init_func
Module initialization functions. The C++ compiler places static constructors here.
example.c
#include <stdio.h>
void myinit(int argc, char **argv, char **envp) {
printf("%s: %s\n", __FILE__, __FUNCTION__);
}
__attribute__((section("__DATA,__mod_init_func"))) typeof(myinit) *__init = myinit;
int main() {
printf("%s: %s\n", __FILE__, __FUNCTION__);
return 0;
}
I build your example with clang on OS X platform:
$ clang -Wall example.c
$ ./a.out
example.c: myinit
example.c: main
Easiest way is to specify the function to be constructor using constructor attribute. The constructor attribute causes the function to be called automatically before execution enters main(). Similarly, the destructor attribute causes the function to be called automatically after main() completes or exit() is called. You can also specify optional priority if you have several functions
e.g. __attribute__((constructor(100)))
#include <stdio.h>
__attribute__((constructor)) void myinit() {
printf("my init\n");
}
int main() {
printf("my main\n");
return 0;
}
__attribute__((destructor)) void mydeinit() {
printf("my deinit\n");
}
$ clang -Wall example.c
$ ./a.out
my init
my main
my deinit
Disclaimer: I generally discourage what I'm about to say. Having code running before or after main makes things less predictable. I'm not sure why you wouldn't just let the first line of main invoke your myinit, but I suppose everyone has a reason. Here goes.
I don't know much about Mach-O, but the simplest way to run code before main, is to link in a C++ class that has a corresponding global instance defined. You can do this independently of your "C" code without having to alter anything else. You can also have this C++ code invoke C functions defined elsewhere in your code. In the example below, I show a simple example of how I would invoke your myinit.
In a standalone .cpp (or .cc) file, declare a very simple C++ class with a constructor that calls your "myinit function".
foo.cpp
// forward declare your myinit function and designate "C" linkage
extern "C" myinit(int, char**, char**);
class CodeToRunBeforeMain
{
public:
CodeToRunBeforeMain()
{
// invoke your myinit function here
myinit(0, NULL, NULL);
}
};
// global instance - constructor will run before main.
CodeToRunBeforeMain g_runBeforeMain;
The above approach doesn't recognize argc, argv, or envp. Hopefully, that isn't important.

Prototype of printf and implementation

I started to wonder how the printf function is declared, it always receive a string as first parameter (well, const char*) and then the rest of the parameters can be a varierty of types, a variable number of them and given in different order.
Does this mean the printf function is declared and overridden for each of the possibilities? This does not make much sense to me, so does it really work like this or it's way different?
Also, how is the function implemented? If it's too complicated I'd just like to know how it works internally in general.
how the printf function is declared
printf is a variadic function and it declared since C99 as follows:
​int printf( const char *restrict format, ... );
^^^
The ... or ellipses indicate that there are a variable number of argument and we would use the va_start, va_arg, va_end macros and va_list type to access the arguments.
how is the function implemented?
and example of a very simple printf is given in the document linked above is as follows and modified to work in C:
#include <stdio.h>
#include <stdarg.h>
void simple_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
while (*fmt != '\0') {
if (*fmt == 'd') {
int i = va_arg(args, int);
printf( "%d\n", i ) ;
} else if (*fmt == 'c') {
int c = va_arg(args, int);
printf( "%c\n", (char)c ) ;
} else if (*fmt == 'f') {
double d = va_arg(args, double);
printf( "%f\n", d ) ;
}
++fmt;
}
va_end(args);
}
int main()
{
simple_printf("dcff", 3, 'a', 1.999, 42.5);
}
The prototype of printf is:
int printf(const char *restrict format, ...);
This feature (the argument ...) is called variable arguments functions. You can do it as well with the help of stdarg.h.
Here's a start: C FAQ: Variable-Length Argument Lists
Each standard library has corresponding header containing the function prototype for all the functions in that library and definitions of various data types and constants that needed by the functions. The header for printf is <stdio.h> which includes its prototype
int printf( const char *restrict format, ... );
Here's a cheesy little program that shows that the prototype for printf is:
int printf ( const char * format, ... );
(and that it doesn't require the restrict keyword as shown by others).
Notice that printf here works withOUT including the otherwise-required stdio.h header file. This is because simply declaring a prototype for the printf function keeps the compiler happy by telling it that this function prototype does indeed exist, and since the object code for the definition (implementation) of printf also happens to exist elsewhere, the linker is happy at the time of linking, after compilation.
Notice the extern "C" {} thing required for C++, however, to prevent the C++ compiler from name-mangling the function name. See the comments above the code for all compile commands I used and tested. Also note that the printing of the "true" stuff is just for kicks, as I was testing some stuff out.
hello_world.c:
/*
hello_world
Gabriel Staples
www.ElectricRCAircraftGuy.com
27 Mar. 2019
Examples of how to compile & run:
- NB: c90 requires C-style comments (slash star, star slash) and does NOT work with modern
C++-style // comments!
C:
gcc -Wall -o hello_world hello_world.c && ./hello_world
gcc -Wall -std=c90 -o hello_world hello_world.c && ./hello_world
gcc -Wall -std=c99 -o hello_world hello_world.c && ./hello_world
gcc -Wall -std=c11 -o hello_world hello_world.c && ./hello_world
C++:
g++ -Wall -o hello_world hello_world.c && ./hello_world
g++ -Wall -std=c++98 -o hello_world hello_world.c && ./hello_world
g++ -Wall -std=c++03 -o hello_world hello_world.c && ./hello_world
g++ -Wall -std=c++11 -o hello_world hello_world.c && ./hello_world
*/
// #include <stdio.h> // for printf
#include <stdbool.h> // for `true` and `false`
#ifdef __cplusplus
extern "C" {
#endif
int printf ( const char * format, ... ); // a hacky alternative to including stdio.h above!
#ifdef __cplusplus
}
#endif
int main(void)
{
printf("Hello World\n");
printf("`true == 1`? = %i, `true == 1`? = %s\n", true, (true == 1 ? "true" : "false"));
return 0;
}
Sample output:
$ gcc -Wall -o hello_world hello_world.c && ./hello_world
Hello World
`true == 1`? = 1, `true == 1`? = true

how to give more than one c file as input to GNU Cflow?

I was able to generate the callgraph of one file using gnu - cflow, but I was not able to find out how to generate the call graph for multiple files using cflow.
I tried following
cflow test.c,hello.c
It generates the callgraph for test.c and not creating it for hello.c
cflow test.c hello.c
It generates the callgraph for hello.c and not creating it for test.c
I don't know how to pass multiple files to cflow.
Any idea about this?
hello.c
int
who_am_i (void)
{
struct passwd *pw;
char *user = NULL;
pw = getpwuid (geteuid ());
if (pw)
user = pw->pw_name;
else if ((user = getenv ("USER")) == NULL)
{
fprintf (stderr, "I don't know!\n");
return 1;
}
printf ("%s\n", user);
unused_function();
return 0;
}
int
main (int argc, char **argv)
{
if (argc > 1)
{
fprintf (stderr, "usage: whoami\n");
return 1;
}
return who_am_i ();
}
void unused_function()
{
printf();
error1();
printf();
}
void error1()
{
error2();
}
void error2()
{
}
test.c
int tests()
{ return 0;}
cflow test.c hello.c
Actually above statement is correct and tests() does not show up in callgraph, because it is never called.
answer given by #AndreasGrapentin
Another convenient command is:
cflow *.c
Note:
This command will ignore C source files in all sub-directories.
Reference:
GNU cflow manual: Chapter 6-Controlling Symbol Types
For cflow to be able to process such declarations, declare __P as a wrapper, for example:
cflow --symbol __P:wrapper *.c

Can a running C program access its own symbol table?

I have a linux C program that handles request sent to a TCP socket (bound to a particular port). I want to be able to query the internal state of the C program via a request to that port, but I dont want to hard code what global variables can be queried. Thus I want the query to contain the string name of a global and the C code to look that string up in the symbol table to find its address and then send its value back over the TCP socket. Of course the symbol table must not have been stripped. So can the C program even locate its own symbol table, and is there a library interface for looking up symbols given their name? This is an ELF executable C program built with gcc.
This is actually fairly easy. You use dlopen / dlsym to access symbols. In order for this to work, the symbols have to be present in the dynamic symbol table. There are multiple symbol tables!
#include <dlfcn.h>
#include <stdio.h>
__attribute__((visibility("default")))
const char A[] = "Value of A";
__attribute__((visibility("hidden")))
const char B[] = "Value of B";
const char C[] = "Value of C";
int main(int argc, char *argv[])
{
void *hdl;
const char *ptr;
int i;
hdl = dlopen(NULL, 0);
for (i = 1; i < argc; ++i) {
ptr = dlsym(hdl, argv[i]);
printf("%s = %s\n", argv[i], ptr);
}
return 0;
}
In order to add all symbols to the dynamic symbol table, use -Wl,--export-dynamic. If you want to remove most symbols from the symbol table (recommended), set -fvisibility=hidden and then explicitly add the symbols you want with __attribute__((visibility("default"))) or one of the other methods.
~ $ gcc dlopentest.c -Wall -Wextra -ldl
~ $ ./a.out A B C
A = (null)
B = (null)
C = (null)
~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic
~ $ ./a.out A B C
A = Value of A
B = (null)
C = Value of C
~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic -fvisibility=hidden
~ $ ./a.out A B C
A = Value of A
B = (null)
C = (null)
Safety
Notice that there is a lot of room for bad behavior.
$ ./a.out printf
printf = ▯▯▯▯ (garbage)
If you want this to be safe, you should create a whitelist of permissible symbols.
file: reflect.c
#include <stdio.h>
#include "reflect.h"
struct sym_table_t gbl_sym_table[1] __attribute__((weak)) = {{NULL, NULL}};
void * reflect_query_symbol(const char *name)
{
struct sym_table_t *p = &gbl_sym_table[0];
for(; p->name; p++) {
if(strcmp(p->name, name) == 0) {
return p->addr;
}
}
return NULL;
}
file: reflect.h
#include <stdio.h>
struct sym_table_t {
char *name;
void *addr;
};
void * reflect_query_symbol(const char *name);
file: main.c
just #include "reflect.h" and call reflect_query_symbol
example:
#include <stdio.h>
#include "reflect.h"
void foo(void)
{
printf("bar test\n");
}
int uninited_data;
int inited_data = 3;
int main(int argc, char *argv[])
{
int i;
void *addr;
for(i=1; i<argc; i++) {
addr = reflect_query_symbol(argv[i]);
if(addr) {
printf("%s lay at: %p\n", argv[i], addr);
} else {
printf("%s NOT found\n", argv[i], addr);
}
}
return 0;
}
file:Makefile
objs = main.o reflect.o
main: $(objs)
gcc -o $# $^
nm $# | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c
gcc -c .reflect.real.c -o .reflect.real.o
gcc -o $# $^ .reflect.real.o
nm $# | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c
gcc -c .reflect.real.c -o .reflect.real.o
gcc -o $# $^ .reflect.real.o
The general term for this sort of feature is "reflection", and it is not part of C.
If this is for debugging purposes, and you want to be able to inspect the entire state of a C program remotely, examine any variable, start and stop its execution, and so on, you might consider GDB remote debugging:
GDB offers a 'remote' mode often used when debugging embedded systems.
Remote operation is when GDB runs on one machine and the program being
debugged runs on another. GDB can communicate to the remote 'stub'
which understands GDB protocol via Serial or TCP/IP. A stub program
can be created by linking to the appropriate stub files provided with
GDB, which implement the target side of the communication
protocol. Alternatively, gdbserver can be used to remotely debug
the program without needing to change it in any way.

Wrapper routine for write() with unistd.h included results in error

I am writing a wrapper routine for write() to override the original system function and within it i need to execute another program through execve(); for which I include the header file unistd.h. I get the error conflicting types for 'write' /usr/include/unistd.h:363:16: note: previous declaration of 'write'was here. I would be very gratefull if someone could help me out as I need to call another program from inside the wrapper and also send arguments to it from inside the wrapper routine.
The GNU linker has a --wrap <symbol> option which allows you to do this sort of thing.
If you link with --wrap write, references to write will redirect to __wrap_write (which you implement), and references to __real_write will redirect to the original write (so you can call it from within your wrapper implementation).
Here's a sophisticated test application using write() - I'm doing the compilation and linking steps separately because I'll want to use hello.o again in a minute:
$ cat hello.c
#include <unistd.h>
int main(void)
{
write(0, "Hello, world!\n", 14);
return 0;
}
$ gcc -Wall -c hello.c
$ gcc -o test1 hello.o
$ ./test1
Hello, world!
$
Here's an implementation of __wrap_write(), which calls __real_write(). (Note that we want a prototype for __real_write to match the original. I've added a matching prototype explicitly, but another possible option is to #define write __real_write before #include <unistd.h>.)
$ cat wrapper.c
#include <unistd.h>
extern ssize_t __real_write(int fd, const void *buf, size_t n);
ssize_t __wrap_write(int fd, const void *buf, size_t n)
{
__real_write(fd, "[wrapped] ", 10);
return __real_write(fd, buf, n);
}
$ gcc -Wall -c wrapper.c
$
Now, link the hello.o we made earlier with wrapper.o, passing the appropriate flags to the linker. (We can pass arbitrary options through gcc to the linker using the slightly odd -Wl,option syntax.)
$ gcc -o test2 -Wl,--wrap -Wl,write hello.o wrapper.o
$ ./test2
[wrapped] Hello, world!
$
An alternative to using the GNU liner --wrap symbol option as suggested by Matthew Slattery would be to use dlsym() to obtain the address of the execve() symbol at runtime in order to avoid the compile-time issues with including unistd.h.
I suggest reading Jay Conrod's blog post entitled Tutorial: Function Interposition in Linux for additional information on replacing calls to functions in dynamic libraries with calls to your own wrapper functions.
The following example provides a write() wrapper function that calls the original write() before calling execve() and does not include unistd.h. It is important to note that you cannot directly call the original write() from the wrapper because it will be interpreted as a recursive call to the wrapper itself.
Code:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
size_t write(int fd, const void *buf, size_t count)
{
static size_t (*write_func)(int, const void *, size_t) = NULL;
static int (*execve_func)(const char *, char *const[], char *const[]) = NULL;
/* arguments for execve() */
char *path = "/bin/echo";
char *argv[] = { path, "hello world", NULL };
char *envp[] = { NULL };
if (!write_func)
{
/* get reference to original (libc provided) write */
write_func = (size_t(*)(int, const void *, size_t)) dlsym(RTLD_NEXT, "write");
}
if (!execve_func)
{
/* get reference to execve */
execve_func = (int(*)(const char *, char *const[], char *const[])) dlsym(RTLD_NEXT, "execve");
}
/* call original write() */
write_func(fd, buf, count);
/* call execve() */
return execve_func(path, argv, envp);
}
int main(int argc, char *argv[])
{
int filedes = 1;
char buf[] = "write() called\n";
size_t nbyte = sizeof buf / sizeof buf[0];
write(filedes, buf, nbyte);
return 0;
}
Output:
$ gcc -Wall -Werror -ldl test.c -o test
$ ./test
write() called
hello world
$
Note: This code is provided as an example of what is possible. I would recommend following Jonathan Leffler's advice on code segregation in constructing the final implementation.
It is an utterly bad idea to try wrapping write() and use POSIX functions. If you chose to work in standard C, then you could wrap write() because it is not a name reserved to the standard. However, once you start using POSIX functions - and execve() is a POSIX function - then you are running into conflicts; POSIX reserves the name write().
If you want to try, you may get away with it if you segregate the code carefully. You have your write() wrapper in one source file which does not include <unistd.h> or use any functions not defined in the C standard for the headers you do include. You have your code that does the execve() in a second file that does include <unistd.h>. And you link those parts together with appropriate function calls.
If you are lucky, it will work as intended. If you aren't lucky, all hell will break loose. And note that your luck status might change on different machines depending on factors outside your control such as o/s updates (bug fixes) or upgrades. It is a very fragile design decision to wrap write().
Just making an illustration for Muggen's attention call (therefore community wiki):
You want to redefine write and call write from inside your redefinition. Something like
void write(int a) {
/* code code code */
write(42); /* ??? what `write`?
??? recursive `write`?
??? the other `write`? */
/* code code code */
}
Better think better about it :)
If you segregate your code appropriately as suggested by Jonathan Leffler, you should be able to avoid compile-time issues related to including unistd.h. The following code is provided as an example of such segregation.
Note that you cannot interpose internal library function calls, since these are resolved before runtime. For instance, if some function in libc calls write(), it will never call your wrapper function.
Code:
exec.c
#include <unistd.h>
inline int execve_func(const char *path, char *const argv[], char *const envp[])
{
return execve(path, argv, envp);
}
test.c
#include <stdio.h>
extern int execve_func(const char *, char *const[], char *const[]);
size_t write(int fd, const void *buf, size_t count)
{
/* arguments for execve() */
char *path = "/bin/echo";
char *argv[] = { path, "hello world", NULL };
char *envp[] = { NULL };
return execve_func(path, argv, envp);
}
int main(int argc, char *argv[])
{
int filedes = 1;
char buf[] = "dummy";
size_t nbyte = sizeof buf / sizeof buf[0];
write(filedes, buf, nbyte);
return 0;
}
Output:
$ gcc -Wall -Werror test.c exec.c -o test
$ ./test
hello world
$

Resources