in gnu library C source code, man could see some of functions prototype are followed with libc_hidden_proto macro, what is used for.
what is used for.
It's documented in inlcude/libc-symbols.h:
/* The following macros are used for PLT bypassing within libc.so
(and if needed other libraries similarly).
First of all, you need to have the function prototyped somewhere,
say in foo/foo.h:
int foo (int __bar);
If calls to foo within libc.so should always go to foo defined in libc.so,
then in include/foo.h you add:
libc_hidden_proto (foo)
line and after the foo function definition:
int foo (int __bar)
{
return __bar;
}
libc_hidden_def (foo)
or
int foo (int __bar)
{
return __bar;
}
libc_hidden_weak (foo)
In other words, this allows GLIBC to call e.g. __mmap which is defined inside libc.so.6 even if you LD_PRELOADed some other library which defines its own __mmap.
Related
I am using library that I shouldn't change it files, that including my h file.
the code of the library looks somthing like like:
#include "my_file"
extern void (*some_func)();
void foo()
{
(some_func)();
}
my problem is that I want that some_func will be extern function and not extern pointer to function (I am implementing and linking some_func). and that how main will call it.
that way I will save little run time and code space, and no one in mistake will change this global.
is it possible?
I thought about adding in my_file.h somthing as
#define *some_func some_func
but it won't compile because asterisk is not allowed in #define.
EDIT
The file is not compiled already, so changes at my_file.h will effect the compilation.
First of all, you say that you can't change the source of the library. Well, this is bad, and some "betrayal" is necessary.
My approach is to let the declaration of the pointer some_func as is, a non-constant writable variable, but to implement it as constant non-writable variable, which will be initialized once for all with the wanted address.
Here comes the minimal, reproducible example.
The library is implemented as you show us:
// lib.c
#include "my_file"
extern void (*some_func)();
void foo()
{
(some_func)();
}
Since you have this include file in the library's source, I provide one. But it is empty.
// my_file
I use a header file that declares the public API of the library. This file still has the writable declaration of the pointer, so that offenders believe they can change it.
// lib.h
extern void (*some_func)();
void foo();
I separated an offending module to try the impossible. It has a header file and an implementation file. In the source the erroneous assignment is marked, already revealing what will happen.
// offender.h
void offend(void);
// offender.c
#include <stdio.h>
#include "lib.h"
#include "offender.h"
static void other_func()
{
puts("other_func");
}
void offend(void)
{
some_func = other_func; // the assignment gives a run-time error
}
The test program consists of this little source. To avoid compiler errors, the declaration has to be attributed as const. Here, where we are including the declarating header file, we can use some preprocessor magic.
// main.c
#include <stdio.h>
#define some_func const some_func
#include "lib.h"
#undef some_func
#include "offender.h"
static void my_func()
{
puts("my_func");
}
void (* const some_func)() = my_func;
int main(void)
{
foo();
offend();
foo();
return 0;
}
The trick is, that the compiler places the pointer variable in the read-only section of the executable. The const attribute is just used by the compiler and is not stored in the intermediate object files, and the linker happily resolves all references. Any write access to the variable will generate a runtime error.
Now all of this is compiled in an executable, I used GCC on Windows. I did not bother to create a separated library, because it doesn't make a difference for the effect.
gcc -Wall -Wextra -g main.c offender.c lib.c -o test.exe
If I run the executable in "cmd", it just prints "my_func". Apparently the second call of foo() is never executed. The ERRORLEVEL is -1073741819, which is 0xC0000005. Looking up this code gives the meaning "STATUS_ACCESS_VIOLATION", on other systems known as "segmentation fault".
Because I deliberately compiled with the debugging flag -g, I can use the debugger to examine more deeply.
d:\tmp\StackOverflow\103> gdb -q test.exe
Reading symbols from test.exe...done.
(gdb) r
Starting program: d:\tmp\StackOverflow\103\test.exe
[New Thread 12696.0x1f00]
[New Thread 12696.0x15d8]
my_func
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000000004015c9 in offend () at offender.c:16
16 some_func = other_func;
Alright, as I intended, the assignment is blocked. However, the reaction of the system is quite harsh.
Unfortunately we cannot get a compile-time or link-time error. This is because of the design of the library, which is fixed, as you say.
You could look at the ifunc attribute if you are using GCC or related. It should patch a small trampoline at load time. So when calling the function, the trampoline is called with a known static address and then inside the trampoline there is a jump instruction that was patched with the real address. So when running, all jump locations are directly in the code, which should be efficient with the instruction cache. Note that it might even be more efficient than this, but at most as bad as calling the function pointer. Here is how you would implement it:
extern void (*some_func)(void); // defined in the header you do not have control about
void some_func_resolved(void) __attribute__((ifunc("resolve_some_func")));
static void (*resolve_some_func(void)) (void)
{
return some_func;
}
// call some_func_resolved instead now
This question already has answers here:
What is a "static" function in C?
(11 answers)
Closed 2 years ago.
What's the difference between the following scenarios?
// some_file.c
#include "some_file.h" // doesn't declare some_func
int some_func(int i) {
return i * 5;
}
// ...
and
// some_file.c
#include "some_file.h" // doesn't declare some_func
static int some_func(int i) {
return i * 5;
}
// ...
If all static does to functions is restrict their accessibility to their file, then don't both scenarios mean some_func(int i) can only be accessed from some_file.c since in neither scenario is some_func(int i) put in a header file?
A static function is "local" to the .c file where it is declared in. So you can have another function (static or nor) in another .c file without having a name collision.
If you have a non static function in a .c file that is not declared in any header file, you cannot call this function from another .c file, but you also cannot have another function with the same name in another .c file because this would cause a name collision.
Conclusion: all purely local functions (functions that are only used inside a .c function such as local helper functions) should be declared static in order to prevent the pollution of the name space.
Example of correct usage:
file1.c
static void LocalHelper()
{
}
...
file2.c
static void LocalHelper()
{
}
...
Example of semi correct usage
file1.c
static LocalHelper() // function is local to file1.c
{
}
...
file2.c
void LocalHelper() // global functio
{
}
...
file3.c
void Foo()
{
LocalHelper(); // will call LocalHelper from file2.c
}
...
In this case the program will link correctly, even if LocalHelpershould have been static in file2.c
Example of incorrect usage
file1.c
LocalHelper() // global function
{
}
...
file2.c
void LocalHelper() // global function
{
}
...
file3.c
void Foo()
{
LocalHelper(); // which LocalHelper should be called?
}
...
In this last case we hava a nema collition and the program wil not even link.
The difference is that with a non-static function it can still be declared in some other translation unit (header files are irrelevant to this point) and called. A static function is simply not visible from any other translation unit.
It is even legal to declare a function inside another function:
foo.c:
void foo()
{
void bar();
bar();
}
bar.c:
void bar()
{ ... }
What's the difference between declaring a function static and not including it in a header?
Read more about the C programming language (e.g. Modern C), the C11 standard n1570. Read also about linkers and loaders.
On POSIX systems, notably Linux, read about dlopen(3), dlsym(3), etc...
Practically speaking:
If you declare a function static it stays invisible to other translation units (concretely your *.c source files, with the way you compile them: you could -at least in principle, even if it is confusing- compile foo.c twice with GCC on Linux: once as gcc -c -O -DOPTION=1 foo.c -o foo1.o and another time with gcc -c -O -DOPTION=2 -DWITHOUT_MAIN foo.c -o foo2.o and in some cases be able to link both foo1.o and foo2.o object files into a single executable foo using gcc foo1.o foo2.o -o foo)
If you don't declare it static, you could (even if it is poor taste) code in some other translation unit something like:
if (x > 2) {
extern int some_func(int); // extern is here for readability
return some_func(x);
}
In practice, I have the habit of naming all my C functions (including static ones) with a unique name, and I generally have a naming convention related to them (e.g. naming them with a common prefix, like GTK does). This makes debugging the program (with GDB) easier (since GDB has autocompletion function names).
At last, a good optimizing compiler could, and practically would often, inline calls to static functions whose body is known. With a recent GCC, compile your code with gcc -O2 -Wall. If you want to check how inlining happened, look into the produced assembler (using gcc -O2 -S -fverbose-asm).
On Linux, you can obtain using dlsym the address of a function which is not declared static.
In computer software, an application binary interface (ABI) is an interface between two binary program modules; often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.
An ABI defines how data structures or computational routines are accessed in machine code, which is a low-level, hardware-dependent format; in contrast, an API defines this access in source code, which is a relatively high-level, relatively hardware-independent, often human-readable format. A common aspect of an ABI is the calling convention, which determines how data is provided as input to or read as output from computational routines; examples are the x86 calling conventions.
-- https://en.wikipedia.org/wiki/Application_binary_interface
I am sure that the standard "Function Calling Sequence" described in Sys V ABI specs (both i386 and AMD64) constraints the calling of those extern functions in a C library, but does it constraints the calling of those static functions too?
Here is an example:
$cat abi.c
#include<stdio.h>
typedef void (*ret_function_t)(int,int);
ret_function_t gl_fp = NULL;
static void prnt(int i, int j){
printf("hi from static prnt:%d:%d\n", i, j);
}
void api_1(int i){
gl_fp = prnt;
printf("hi from extern api_1:%d\n", i);
}
ret_function_t api_2(void){
return gl_fp;
}
$cat abi_main.c
#include<stdio.h>
typedef void (*ret_function_t)(int,int);
extern void api_1(int i);
extern ret_function_t api_2(void);
int main(){
api_1(1111);
api_2()(2222, 3333);
}
$gcc abi_main.c abi.c -o abi_test
$./abi_test
hi from extern api_1:1111
hi from static prnt:2222:3333
The function calling sequence (including registers usage, stack frame, parameters passing, variable arguments...) details are defined in the Sys V ABI when abi_main.c call the api_1 and api_2 since they are extern, but what about the calling of the static function prnt which been defined in abi.c? Does it belong to the ABI standard or to the compiler to decide?
Yes, they do apply. Static functions are just plain functions with traslation-unit visibility. The ABI is a compiler generation task, C standard deliberately says nothing about it. It becomes clear when removing the static word from your code. The reasoning is the same. The drawback with this approach is that compiler cannot check the linkage right (caller-callee), but only its type (void (*ret_function_t)(int,int);) at compile time, since you are the one who links at runtime. So, it is not recommended.
What happens is that your compiler will generate code for any calling function, following some ABI, lets call it ABI-a. And it will generate code for
a function being called according to some other ABI, lets say ABI-b. If ABI-a == ABI-b, that always work, and this is the case if you compile both files with the same ABI.
For example, this works if prnt function were located at address 0x12345678:
ret_function_t gl_fp = (ret_function_t)0x12345678;
It also works as long as there is a function with the right arguments at 0x12345678. As you can see, the function cannot be inlined because the compiler does not know which function definition will end up in that memory spot, there could be many.
I have a homework assignment that requires us to open, read and write to file using system calls rather than standard libraries. To debug it, I want to use std libraries when test-compiling the project. I did this:
#ifdef HOME
//Home debug prinf function
#include <stdio.h>
#else
//Dummy prinf function
int printf(const char* ff, ...) {
return 0;
}
#endif
And I compile it like this: gcc -DHOME -m32 -static -O2 -o main.exe main.c
Problem is that I with -nostdlib argument, the standard entry point is void _start but without the argument, the entry point is int main(const char** args). You'd probably do this:
//Normal entry point
int main(const char** args) {
_start();
}
//-nostdlib entry point
void _start() {
//actual code
}
In that case, this is what you get when you compile without -nostdlib:
/tmp/ccZmQ4cB.o: In function `_start':
main.c:(.text+0x20): multiple definition of `_start'
/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o:(.text+0x0): first defined here
Therefore I need to detect whether stdlib is included and do not define _start in that case.
The low-level entry point is always _start for your system. With -nostdlib, its definition is omitted from linking so you have to provide one. Without -nostdlib, you must not attempt to define it; even if this didn't get a link error from duplicate definition, it would horribly break the startup of the standard library runtime.
Instead, try doing it the other way around:
int main() {
/* your code here */
}
#ifdef NOSTDLIB_BUILD /* you need to define this with -D */
void _start() {
main();
}
#endif
You could optionally add fake arguments to main. It's impossible to get the real ones from a _start written in C though. You'd need to write _start in asm for that.
Note that -nostdlib is a linker option, not compile-time, so there's no way to automatically determine at compile-time that that -nostdlib is going to be used. Instead just make your own macro and pass it on the command line as -DNOSTDLIB_BUILD or similar.
What I would like is a tool to be able to tell me which functions call a particular function A() (in a C project), and which functions call those functions etc so that I can have a list of functions which i know that when they are called, there is a possibility that function A() will be called.
For example we have the following functions scattered in a project:
void A()
{ /*does something*/ }
void B()
{
A();
/*and more stuff*/
}
void C()
{
if(unlikely_to_be_false)
A()
/* moar stoff */
}
void D()
{
/* code that does not refer to A() at all */
}
void E()
{
C()
}
When the awesome tool is run with parameter A, It will return somehow a the functions B C and E.
Close to this but not exactly i would like to accomplish this:
Given a variable somewhere in a project find all read/write operations(direct or indirect) to it.
For example:
void A()
{
char* c; // this is our little variable
B(c); // this is in the resulting list
}
void B(char* x)
{
printf("%c", x); // this is definately in the list
*x='d' // this is also in the list
C(x); // also in the list
}
void C(void* ptr)
{
ptr = something; // also in the list
}
If the above could play well with emacs i would be most delighted!
You could have a look on cscope tool (http://cscope.sourceforge.net/). It supports very large projects and a lot of different queries type :
Find this C symbol
Find this global definition
Find functions called by this function
Find functions calling this function
...
First, there is the issue of calls between different compilation units, e.g. foo.c defining function foo1 calling function bar2 defined in bar.c (and that bar2 might call a foobar defined in foo.c or in another file foofoo.c)
Then, you might consider perhaps developing a GCC plugin or a MELT extension to suit your needs.
You could also buy a costly static analyzer tool.
Emacs has cedet which might interest you.