Know exact line of the program execution - c

I am trying to do a debug mode for my program that writes something like this in one file to store the logs:
[Day Month D HH:MM:SS YYYY] foo.c function_name line 33: The thing
that happens
The problem is know the exactly value of the line, obviously I can see it in my IDE, but I want to know if exist a more elegant and efficient way.
I hope you have explained me well (sorry if not) and thanks in advance.

You may have a look at macro assert (assert.h) where it is done as intended by you.
In short:
It has to be a macro. If it were a function it would report the file and line of this function but actually you would want the file and line where the function is called. (This does not mean that this macro cannot call a function as helper.)
The current file and line are accessible by the macros __FILE__ and __LINE__.
So this is how it could look in source code:
#define LOG_DEBUG(TEXT) log_debug(__FILE__, __LINE__, TEXT)
void log_debug(const char *file, int line, const char *text)
{
fprintf(stderr, "DEBUG '%s':%d: %s\n");
}
As MCVE test-log-debug.c:
#include <stdio.h>
#define LOG_DEBUG(TEXT) log_debug(__FILE__, __LINE__, TEXT)
void log_debug(const char *file, int line, const char *text)
{
fprintf(stderr, "DEBUG '%s':%d: %s\n", file, line, text);
}
/* test/sample */
int main()
{
LOG_DEBUG("in main()");
return 0;
}
Compiled and tested with gcc in cygwin on Windows 10 (64 bit):
$ gcc --version
gcc (GCC) 6.4.0
$ gcc -std=c11 -g -o test-log-debug test-log-debug.c
$ ./test-log-debug
DEBUG 'test-log-debug.c':13: in main()
$
Compiled and tested in VS2013 on Windows 10 again:
DEBUG 'C:\Users\Scheff\tests\test-log-debug.c':13: in main()
visibleman noted that there is a very similar question SO: Visual C++ equivalent of __FILE__ , __LINE__ and __PRETTY_FUNCTION__.
AFAIK, (and also mentioned in one that answers) __FILE__ and __LINE__ are standard. Other/similar macros might be provided as proprietary extension of the compiler.

Related

No output from split up source, but no warnings either, when omitting an included file

I ran into an issue invoking gcc where if I omit a library .c file, I got no output from the binary (unexpected behavior change) but since this is a missing dependency, I kind of expected the compile to fail (or at least warn)...
Example for this issue is from Head First C page 185 (but is not errata, see my compile mis-step below):
encrypt.h:
void encrypt(char *message);
encrypt.c:
#include "encrypt.h"
void encrypt(char *message)
{
// char c; errata
while (*message) {
*message = *message ^ 31;
message++;
}
}
message_hider.c:
#include <stdio.h>
#include "encrypt.h"
int main() {
char msg[80];
while (fgets(msg, 80, stdin)) {
encrypt(msg);
printf("%s", msg);
}
}
NOW, everything works fine IF I faithfully compile as per exercise instruction:
gcc message_hider.c encrypt.c -o message_hider
... but bad fortune led me to compile only the main .c file, like so:
$ gcc message_hider.c -o message_hider
This surprisingly successfully builds, even if I added -Wall -Wextra -Wshadow -g.
Also surprisingly, it silently fails, with no output from encrypt() function:
$ ./message_hider < ./encrypt.h
$
my gcc is:
$ /usr/bin/gcc --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Mindful that even with a Makefile, I could "still" end up with a missing .c file due to a mistake in the recipe.
Q: Is it possible to force a hard error if I forget to tell gcc about a .c file?
As I noted in a (misspelled) comment:
There is probably a function encrypt() in the system library.
On a Mac, man -s 3 encrypt shows:
CRYPT(3) BSD Library Functions Manual CRYPT(3)
NAME
crypt, encrypt, setkey -- DES encryption
SYNOPSIS
#include <unistd.h>
char *
crypt(const char *key, const char *salt);
void
encrypt(char *block, int edflag);
#include <stdlib.h>
void
setkey(const char *key);
…
The encrypt() and setkey() functions are part of POSIX, so they'll be available on most POSIX-like systems. Curiously, as shown in the manual page extract, the functions are declared in separate headers — <unistd.h> for encrypt() and
<stdlib.h> for setkey(). There's probably a good (enough) historical reason for the disconnect.
You should have received a compiler warning about the function being undeclared — if you didn't, you are presumably compiling using the C90 standard. That is very old and should not still be being taught; you need to be learning C11 or C18 (almost the same).
Since C99, the C standard requires functions to be declared before use — you can define a static function without pre-declaring it, but all other functions (except main()) should be declared before they are used or defined. You can use GCC compiler warning options such as -Wmissing-prototypes -Wstrict-prototypes (along with -Wold-style-declaration and -Wold-style-definition) to trigger warnings. Of these, -Wold-style-declaration is enabled by -Wextra (and none by -Wall). Be aware: as noted in the comments, clang does not support -Wold-style-declaration though true GCC (not Apple's clang masquerading as gcc) does support it.

How to Compile a C program which contains 32bit asm into .o file?

Introduction
I'm following through the book "Learning Linux Binary Analysis". I have some experience working with 32 bit assembly and C (however still consider myself a novice). However I'm having trouble and confusion of how to compile a c program , which contains 32 bit assembly into an object file .o. So im guessing this is just a compilation issue on my part.
The Source code is for part of an example of code injection-based binary patching.
Source Code
#include <sys/syscall.h>
int _write (int fd, void *buf, int count)
{
long ret;
__asm__ __volatile__ ("pushl %%ebx\n\t"
"movl %%esi,%%ebx\n\t"
"int $0x80\n\t""popl %%ebx":"=a" (ret)
:"0" (SYS_write), "S" ((long) fd),
"c" ((long) buf), "d" ((long) count));
if (ret >= 0) {
return (int) ret;
}
return -1;
}
int evil_puts(void)
{
_write(1, "HAHA puts() has been hijacked!\n", 31);
}
The problem
I attempt to compile evil_puts.c into .o file. Which will then be used later for injection into another simple program.
gcc -c evil_puts.c
evil_puts.c: Assembler messages:
evil_puts.c:5: Error: invalid instruction suffix for `push'
evil_puts.c:8: Error: invalid instruction suffix for `pop'
I've received this before when working with 32 assembly with gas. And to solve this i put the '-32' flag when compiling and linking. Which i'm guessing is the problem? however not completely sure, and don't have an idea of how to compile it in 32 bit with C and gcc if that's the case?
I also attempted to change it to 64bit to see if it would work, by replacing 'l' of every command to 'q' and changing the registers to begin with 'r'. which seems to work. However the book uses 32 bit. So i wish to keep it that way. Any ideas? Sorry if this is a really basic question.
Also tried '-m32' but receive this:
fatal error: sys/syscall.h: No such file or directory
Use gcc -m32 -c evil_puts.c -o evil_puts.o
You're getting that error because you don't have the 32-bit libraries installed.
If using Ubuntu:
sudo apt-get install gcc-multilib
Knowledge specific to 32-bit x86 is of limited usefulness these days since basically everybody has switched to 64-bit (this is a good thing - 32-bit has a lot of register pressure and address space pressure).
Luckily, you don't actually need any asm for what you're doing. I've also made a couple sanity fixes:
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#define write_str(fd, s) my_write(fd, s, strlen(s))
static ssize_t my_write(int fd, const void *buf, size_t count)
{
return syscall(SYS_write, (long)fd, (long)buf, (long)count);
}
int puts(const char *s __attribute__((unused)))
{
write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n");
return strlen(s) + 1;
}
I'm not sure exactly why you're avoiding write(2). But if you really need to avoid syscall(2) as well, it will still be far easier to implement that single function in assembly than write assembly everywhere.

Check if a system implements a function

I'm creating a cross-system application. It uses, for example, the function itoa, which is implemented on some systems but not all. If I simply provide my own itoa implementation:
header.h:115:13: error: conflicting types for 'itoa'
extern void itoa(int, char[]);
In file included from header.h:2:0,
from file.c:2:0,
c:\path\to\mingw\include\stdlib.h:631:40: note: previous declaration of 'itoa' was here
_CRTIMP __cdecl __MINGW_NOTHROW char* itoa (int, char*, int);
I know I can check if macros are predefined and define them if not:
#ifndef _SOME_MACRO
#define _SOME_MACRO 45
#endif
Is there a way to check if a C function is pre-implemented, and if not, implement it? Or to simply un-implement a function?
Given you have already written your own implementation of itoa(), I would recommend that you rename it and use it everywhere. At least you are sure you will get the same behavior on all platforms, and avoid the linking issue.
Don't forget to explain your choice in the comments of your code...
I assume you are using GCC, as I can see MinGW in your path... there's one way the GNU linker can take care of this for you. So you don't know whether there is an itoa implementation or not. Try this:
Create a new file (without any headers) called my_itoa.c:
char *itoa (int, char *, int);
char *my_itoa (int a, char *b, int c)
{
return itoa(a, b, c);
}
Now create another file, impl_itoa.c. Here, write the implementation of itoa but add a weak alias:
char* __attribute__ ((weak)) itoa(int a, char *b, int c)
{
// implementation here
}
Compile all of the files, with impl_itoa.c at the end.
This way, if itoa is not available in the standard library, this one will be linked. You can be confident about it compiling whether or not it's available.
Ajay Brahmakshatriya's suggestion is a good one, but unfortunately MinGW doesn't support weak definition last I checked (see https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ, for instance).
However, I believe weak references do work in MinGW. Take this minimal example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
__attribute__ ((weak)) char* itoa (int, char*, int);
char* my_itoa (int a, char* b, int c)
{
if(itoa != NULL) {
return itoa(a, b, c);
} else {
// toy implementation for demo purposes
// replace with your own implementation
strcpy(b, "no itoa");
return b;
}
}
int main()
{
char *str = malloc((sizeof(int)*3+1));
my_itoa(10, str, 10);
printf("str: %s\n", str);
return 0;
}
If the system provides an itoa implementation, that should be used and the output would be
str: 10
Otherwise, you'll get
str: no itoa
There are two really important related points worth making here along the "don't do it like this" lines:
Don't use atoi because it's not safe.
Don't use atoi because it's not a standard function, and there are good standard functions (such as snprintf) which are available to do what you want.
But, putting all this aside for one moment, I want to introduce you to autoconf, part of the GNU build system. autoconf is part of a very comprehensive, very portable set of tools which aim to make it easier to write code which can be built successfully on a wide range of target systems. Some would argue that autoconf is too complex a system to solve just the one problem you pose with just one library function, but as any program grows, it's likely to face more hurdles like this, and getting autoconf set up for your program now will put you in a much stronger position for the future.
Start with a file called Makefile.in which contains:
CFLAGS=--ansi --pedantic -Wall -W
program: program.o
program.o: program.c
clean:
rm -f program.o program
and a file called configure.ac which contains:
AC_PREREQ([2.69])
AC_INIT(program, 1.0)
AC_CONFIG_SRCDIR([program.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for library functions.
AH_TEMPLATE([HAVE_ITOA], [Set to 1 if function atoi() is available.])
AC_CHECK_FUNC([itoa],
[AC_DEFINE([HAVE_ITOA], [1])]
)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
and a file called program.c which contains:
#include <stdio.h>
#include "config.h"
#ifndef HAVE_ITOA
/*
* WARNING: This code is for demonstration purposes only. Your
* implementation must have a way of ensuring that the size of the string
* produced does not overflow the buffer provided.
*/
void itoa(int n, char* p) {
sprintf(p, "%d", n);
}
#endif
int main(void) {
char buffer[100];
itoa(10, buffer);
printf("Result: %s\n", buffer);
return 0;
}
Now run the following commands in turn:
autoheader: This generates a new file called config.h.in which we'll need later.
autoconf: This generates a configuration script called configure
./configure: This runs some tests, including checking that you have a working C compiler and, because we've asked it to, whether an itoa function is available. It writes its results into the file config.h for later.
make: This compiles and links the program.
./program: This finally runs the program.
During the ./configure step, you'll see quite a lot of output, including something like:
checking for itoa... no
In this case, you'll see that the config.h find contains the following lines:
/* Set to 1 if function atoi() is available. */
/* #undef HAVE_ITOA */
Alternatively, if you do have atoi available, you'll see:
checking for itoa... yes
and this in config.h:
/* Set to 1 if function atoi() is available. */
#define HAVE_ITOA 1
You'll see that the program can now read the config.h header and choose to define itoa if it's not present.
Yes, it's a long way round to solve your problem, but you've now started using a very powerful tool which can help you in a great number of ways.
Good luck!

How to override fprintf in the C library? How to add GCC option to toplevel CMakeLists.txt?

I know how to overwrite C-lib functions in just simple sample. But what I need is IN A REAL PROJECT which has hundreds of files that call fprintf.
In each file, there's a "#include < stdio.h >", and tens or hundreds of calls of fprintf. I wanna make all these fprintf to do my own job. I cannot remove the "stdio.h" and put a "#include < myprint.h >", where myprint.h defines the real function or macro of fprintf that do my own job. "stdio.h" has many other calls in the project. I want a simple enough solution.
Thanks!
Do I make my question clear enough?...
Update on 2014.03.08:
Salute to all women at first...
Please see my 2nd post below.
If you are using gcc for example, you can invoke it in the following way:
gcc -include myheader.h -Dfprintf=myfprintf file.c
And that will include myheader.h before every other include header in file.c and will redefine fprintf as myfprintf.
You can find more details here
Question update overview: I added GCC option to CMAKE, but it seems not working.
====== SOLUTION TO MY FIRST POST ======
Hi all,
As for the question in my first post, I found a hook solution as follows:
#define _GNU_SOURCE
// for time() and localtime()
#include <time.h>
// for fprintf/fwrite
#include <stdio.h>
// for va_* functions
#include <stdarg.h>
// for dlsym
#include <dlfcn.h>
// compile command line: gcc -shared -Wl,--no-as-needed -ldl -fPIC -Wall hooktest.c -o hooktest.so
// how to use: LD_PRELOAD=hooktest.so ./hooktestprog, where hooktestprog includes stdio.h and calls fprintf
// a helper function
void print_time(FILE *fp, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(fp, format, args);
va_end(args);
}
// GCC optimizes fprintf to fwrite
// to make original program use fprintf exactly, compile the program (not this library) with -fno-builtin-fprintf
int fprintf(FILE *stream, const char *format, ...)
{
static int (*my_fprintf)(FILE *stream, const char *format, ...) = NULL;
if (NULL == my_fprintf)
{
my_fprintf = (int (*)(FILE *stream, const char *format, ...))dlsym(RTLD_NEXT, "fprintf");
}
va_list args;
va_start(args, format);
time_t tNow = time(NULL);
struct tm *tmNow = localtime(&tNow);
print_time(stream, "%04d/%02d/%02d %02d:%02d:%02d === ", tmNow->tm_year+1900, tmNow->tm_mon+1, tmNow->tm_mday, tmNow->tm_hour, tmNow->tm_min, tmNow->tm_sec);
my_fprintf(stream, format, args);
va_end(args);
return 0;
}
// GCC optimizes fprintf to fwrite
// to make original program use fprintf exactly, compile the program (not this library) with -fno-builtin-fprintf
/* size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
static size_t (*my_fwrite)(const void *, size_t, size_t, FILE *) = NULL;
if (NULL == my_fwrite)
{
my_fwrite = (size_t (*)(const void *, size_t, size_t, FILE *))dlsym(RTLD_NEXT, "fwrite");
}
time_t tNow = time(NULL);
struct tm *tmNow = localtime(&tNow);
print_time(stream, "%04d/%02d/%02d %02d:%02d:%02d === ", tmNow->tm_year+1900, tmNow->tm_mon+1, tmNow->tm_mday, tmNow->tm_hour, tmNow->tm_min, tmNow->tm_sec);
my_fwrite(ptr, size, nmemb, stream);
FILE *fp = fopen("/home/idesclient/log_freerdp.log", "a");
if (NULL != fp)
{
print_time(fp, "%04d/%02d/%02d %02d:%02d:%02d === ", tmNow->tm_year+1900, tmNow->tm_mon+1, tmNow->tm_mday, tmNow->tm_hour, tmNow->tm_min, tmNow->tm_sec);
my_fwrite(ptr, size, nmemb, fp);
fclose(fp);
}
return nmemb;
} */
I wanna override fprintf, but GCC optimizes fprintf to fwrite. You can check this by writing a sample that calls fprintf, compile it, and use the command "nm yoursample | grep #GLIBC_2.0". you can see something like "fwrite#GLIBC_2.0", and there is NO "fprintf#GLIBC_2.0".
But I cannot override fwrite because there are other fwrite calls in my project. As you can see, I commented out fwrite().
I found another solution: add "-fno-builtin-fprintf" while compiling a sample program, and now the sample works. NOTE: only the sample works, not my project works... The command line is as follows:
>gcc -shared -Wl,--no-as-needed -ldl -fPIC -Wall hooktest.c -o hooktest.so
>gcc -fno-builtin-fprintf sample.c -o sample # where sample.c calls fprintf
>LD_PRELOAD=./hooktest.so ./sample
Now I can see fprintf adds time information - fprintf is hooked.
====== NEW QUESTION STARTS HERE ======
By now, it seems I can add "-fno-builtin-fprintf" to my toplevel CMakeLists.txt (the project has many subdirectories, it's quite a complex project), and everythind SHOULD work. But in real practice, it does not.
I have the following lines in my toplevel CMakeLists.txt:
if(CMAKE_COMPILER_IS_GNUCC)
xxxxxx (this is the original definitions in my project)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin-fprintf")
endif()
But after I compile the project, use "LD_PRELOAD=/xxx/hooktest.so /xxx/project/bin/somebinary", fprintf is not hooked.
I do another test. In my C code above, I comment fprintf and uncomment fwrite (GCC optimizes fprintf to fwrite, see expaination above), and remove the "-fno-builtin-fprintf" in the toplevel CMakeLists.txt. I can see fprintf hooked to fwrite in my code, but only fprintf(stderr, "xxx") hooked, but fprintf(stderr, "xxx %s %d xxx", somestring, someinteger) not hooked. It seems that fprintf with % and more than 2 arguments cannot be hooked.
Please help to debug this. Thanks!

Compiling with Mingw

I have a bunch of C files and header files in the folder. When I compile the C files with MinGW compiler, it shows that there is no such file or directory. But I have all the files in the same folder. How do I get them to compile?
I have attached the code for your reference (file computil.c):
#include <stdio.h>
#include <computil.h>
#include <dataio.h>
int getc_skip_marker_segment(const unsigned short marker, unsigned char **cbufptr, unsigned char *ebufptr)
{
int ret;
unsigned short length;
ret = getc_ushort(&length, cbufptr, ebufptr);
if(ret)return(ret);
length -= 2;
if(((*cbufptr)+length) >= ebufptr)
{
fprintf(stderr, "ERROR : getc_skip_marker_segment : ");
fprintf(stderr, "unexpected end of buffer when parsing ");
fprintf(stderr, "marker %d segment of length %d\n", marker, length);
return(-2); }(*cbufptr) += length; return(0);
}
}
I am compiling it with gcc -c computil.c.
I believe you are going to have to add the current directory to the list of "standard places" that gcc uses. When you use instead of "computil.h", a Unix-style compiler won't look in the current directory.
For a quick fix to that, add -I. to the gcc command line. (dash, capital eye, period):
gcc -I. computil.c
If that's an application include file intended to be found where the source files are found, then you should change the include line to:
#include "computil.h"
That's one of the valuable nuances from Classic C that got lost in the ANSI standardization process. Standard C lets the compiler decide if there's a difference or between <> bracketed and "" quoted headers. It makes a difference in Unix and GNU ("GNU's Not Unix!"), well, pretty much is Unix only better in places.
To put it simple, #include <header.h> means "search in the compiler's own library directories, while #include "header.h means "search in the same directory as the .c file that made the #include".
I don't believe gcc has any library headers named computil.h and dataio.h, so the code won't compile.

Resources