I am trying to use the 'environ' variable, but it keeps giving me an error. It seems to be a makefile/build error and I can't seem to fix it. I have searched fo answers, but still I am lost.
Here is my c file:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include "cmd.h"
int cmdExec() {
...
extern char **environ;
...
printf("Enter a command\n");
//gets (input);
scanf("%s%*[^\n]", input);
if (...) {
...
}
else if (strcmp(input, "environ") == 0) {
int i;
for (i = 0; environ[i] != NULL; i++) {
printf("%s\n", environ[i]);
}
exit(0);
else
...
return 0;
}
and here is the makefile:
CC = gcc
CFLAGS = -c
CFLAGS-y = -std=c99
all: cmd
cmd.o: cmd.c cmd.h
$(CC) $(CFLAGS) $(CFLAGS-y) cmd.c
cmd.exe: cmd.o
$(CC) -o cmd.exe cmd.o
clean:
rm -rf *.o cmd.exe a.out
This is the output:
make all
gcc -c -std=c99 cmd.c
gcc cmd.o -o cmd
cmd.o:cmd.c:(.text+0x105): undefined reference to `environ'
cmd.o:cmd.c:(.text+0x127): undefined reference to `environ'
collect2: ld returned 1 exit status
make: *** [cmd] Error 1
From what I've searched this deals with linking libraries, but I don't know how to apply that to my specific situation. If someone could give me a hand I'd appreciate it.
Not all(if any) compilers on Windows provides access to environment variables through a global symbol named environ.
You can use e.g. getenv() to access environment variables.
The win32 API provides GetEnvironmentStrings() to access all the variables.
Some platforms allow you to access the environment through an additional argument to main(), you'd declare your main function as:
int main(int argc, char *argv[], char *environ[])
The environ global variable is defined by POSIX, and is not supported by Windows (unless you're using Cygwin, which is a POSIX-like layer implemented on top of Windows).
As far as I know, the non-standard definition
int main(int argc, char **argv, char **envp) { /* ... */ }
is also not supported on Windows.
But a quick Google search turned up this answer, which points to the documentation for the Windows-specific GetEnvironmentStrings function:
LPTCH WINAPI GetEnvironmentStrings(void);
If the function succeeds, the return value is a pointer to the
environment block of the current process.
If the function fails, the return value is NULL.
The result points to a long string with the environment variables separated by '\0' null characters, with the environment terminated by two consecutive null characters.
LPTCH is Microsoft's typedef for a pointer to either unsigned char or a 16-bit wchar_t. See the referenced documentation for more information.
Related
i have a c file named main.c
#include <stdio.h>
extern int main(int argc, char* argv[], char* envp[]);
void start(){
...;
int return_code = main(argc, argv, envp);
exit(return_code);
}
you can see I declared main but when using ld to link it:
$ (use ld to link, I didn't write it down because it's quite verbose and irrelevant)
ld: bin/test.o: in function `start':
/home/user/Desktop/test/test.c:28: undefined reference to `main'
make: *** [Makefile:49: link] Error 1
so what should i do (sorry if this is a simple question for you)
In C you have to define a main function that will be called automatically by your program, this is the base of your code.
I saw that you include "stdio.h" which is a library allowing to have access to some function like for example in my program the function "printf".
If you don't need it then don't include it :)
For example here is how to make your first program with a main function.
#include <stdio.h>
int main(int argc, char *argv[]){
... // Your code
printf("Hello world"); // Just print on your terminal this string
return (0); // 0 is the default return code if there is no errors
}
Generally speaking, invoking ld yourself is being a glutton for punishment. Use your C compiler to link until proven otherwise.
gcc -o bin/test bin/test.o will link a C program for you.
It looks like you tried to "fix" it by providing _start yourself. You can't (in C). _start is not a function.
I want to load a shared library with dlopen and have the symbols in it available without having to individually grab function pointers to them with dlsym. The man page says that the RTLD_DEEPBIND flag will place lookup of symbols in the library ahead of global scope, but evidently this does not mean it overrides existing symbols because this does not work. Consider this example:
main.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
int is_loaded(){return 0;}
int main(){
void *h = dlopen("./libimplementation.so", RTLD_NOW | RTLD_DEEPBIND);
if(!h){
printf("Could not load implementation: %s\n", dlerror());
return 1;
}
puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
dlclose(h);
}
implementation.c:
int is_loaded(){return 1;}
Makefile:
all: main libimplementation.so
main: main.c
gcc -Wall -std=c99 -o $# $^ -ldl
lib%.so: %.c
gcc -Wall -std=c99 -o $# $^ -shared
clean:
-rm main *.so
When I build and run with make and ./main, I expect the test() function from libimplementation.so to override the test() function from main but it doesn't. I know I could also move all of the code in main() into another shared library run and then have main() dlopen libimplementation.so with RTLD_GLOBAL and then have librun.so refer to the symbols from libimplementation.so without having them defined so it loads them:
modified main.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
int main(){
void *impl_h = dlopen("./libimplementation.so", RTLD_LAZY | RTLD_GLOBAL);
if(!impl_h){
printf("Could not load implementation: %s\n", dlerror());
return 1;
}
void *run_h = dlopen("./librun.so", RTLD_LAZY);
if(!run_h){
printf("Could not load run: %s\n", dlerror());
dlclose(impl_h);
return 1;
}
void (*run)(void);
*(void**)&run = dlsym(run_h, "run");
if(!*(void**)&run){
printf("Could not find entry point in run: %s\n", dlerror());
dlclose(impl_h);
dlclose(run_h);
return 1;
}
run();
dlclose(impl_h);
dlclose(run_h);
}
run.c:
#include <stdio.h>
int is_loaded(void);
void run(void){
puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
}
and the Makefile gets librun.so added as a prerequisite for all.
Is there a way to get the symbols from the shared library available all at once without dlsym or putting the actual code in another shared library like with librun.so?
There is fundamentally no way to do what you're asking for. Imagine the main program had something like:
static char *myptr = array_in_lib1;
Later, at the time you dlopen, myptr has some other value. Has the program just changed the variable to point to a different object? Or has it been incremented to point to some element later in the array - in which case, would you want it adjusted to account for the redefinition of array_in_lib1 with a new definition from the newly-opened library? Or is it just a random integer cast to char *? Deciding how to treat it is impossible without understanding programmer intent and full process history of how it arrived in the current state.
The above is a particulrly egregious sort of example I've constructed, but the idea of symbols changing definition at runtime is fundamentally inconsistent in all sorts of ways. Even RTLD_DEEPBIND, in what it already does, is arguably inconsitent and buggy. Whatever you're trying to do, you should find another way to do it.
I am using dlsym to look up symbols in my program, but it always returns NULL, which I am not expecting. According to the manpage, dlsym may return NULL if there was an error somehow, or if the symbol indeed is NULL. In my case, I am getting an error. I will show you the MCVE I have made this evening.
Here is the contents of instr.c:
#include <stdio.h>
void * testing(int i) {
printf("You called testing(%d)\n", i);
return 0;
}
A very simple thing containing only an unremarkable example function.
Here is the contents of test.c:
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
typedef void * (*dltest)(int);
int main(int argc, char ** argv) {
/* Declare and set a pointer to a function in the executable */
void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
dlerror();
dltest fn = dlsym(handle, "testing");
if(fn == NULL) {
printf("%s\n", dlerror());
dlclose(handle);
return 1;
}
dlclose(handle);
return 0;
}
As I step through the code with the debugger, I see the dlopen is returning a handle. According to the manpage, If filename is NULL, then the returned handle is for the main program. So if I link a symbol called testing into the main program, dlsym should find it, right?
Here is the way that I am compiling and linking the program:
all: test
instr.o: instr.c
gcc -ggdb -Wall -c instr.c
test.o: test.c
gcc -ggdb -Wall -c test.c
test: test.o instr.o
gcc -ldl -o test test.o instr.o
clean:
rm -f *.o test
And when I build this program, and then do objdump -t test | grep testing, I see that the symbol testing is indeed there:
08048632 g F .text 00000020 testing
Yet the output of my program is the error:
./test: undefined symbol: testing
I am not sure what I am doing wrong. I would appreciate if someone could shed some light on this problem.
I don't think you can do that, dlsym works on exported symbols. Because you're doing dlsym on NULL (current image), even though the symbols are present in the executable ELF image, they're not exported (since it's not a shared library).
Why not call it directly and let the linker take care of it? There's no point in using dlsym to get symbols from the same image as your dlsym call. If your testing symbol was in a shared library that you either linked against or loaded using dlopen then you would be able to retrieve it.
I believe there's also a way of exporting symbols when building executables (-Wl,--export-dynamic as mentioned in a comment by Brandon) but I'm not sure why you'd want to do that.
I faced the similar issue in my code.
I did the following to export symbols
#ifndef EXPORT_API
#define EXPORT_API __attribute__ ((visibility("default")))
#endif
Now for each of the function definition I used the above attribute.
For example the earlier code was
int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
I changed to
EXPORT_API int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
Now it works.
dlsym gives no issues after this.
Hope this works for you as well.
I am exploring some adventurous ideas.
TL:DR; gnumake is able to use loadable modules, I am trying to use that C barrier to use OCaml but have trouble with the OCaml runtime initializing.
I have this OCaml code:
(* This is speak_ocaml.ml *)
let do_speak () =
print_endline "This called from OCaml!!";
flush stdout;
"Some return value from OCaml"
let () =
Callback.register "speak" do_speak
and I also have this C code: (Yes, needs to use extra CAML macros but not relevant here)
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <gnumake.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/memory.h>
#include <caml/alloc.h>
int plugin_is_GPL_compatible;
char *ocaml_speaker(const char *func_name, int argc, char **argv)
{
char *answer =
String_val(caml_callback(*caml_named_value("speak"), Val_unit));
printf("Speaking and got: %s\n", answer);
char *buf = gmk_alloc(strlen(answer) + 1);
strcpy(buf, answer);
/* receive_arg */
return buf;
}
int do_speak_gmk_setup()
{
printf("Getting Called by Make\n");
// This is pretty critical, will explain below
char **argv = {"/home/Edgar/foo", NULL};
caml_startup(argv);
printf("Called caml_startup\n");
gmk_add_function("speak", ocaml_speaker, 1, (unsigned int)1, 1);
return 1;
}
and I'm compiling it with this Makefile
all:
ocamlopt -c speak_ocaml.ml
ocamlopt -output-obj -o caml_code.o speak_ocaml.cmx
clang -I`ocamlc -where` -c do_speak.c -o do_speak.o
clang -shared -undefined dynamic_lookup -fPIC -L`ocamlc -where` -ldl \
-lasmrun do_speak.o caml_code.o -o do_speak.so
show_off:
echo "Speaker?"
${speak 123}
clean:
#rm -rf *.{cmi,cmt,cmi,cmx,o,cmo,so}
And my problem is that only printf("Getting Called by Make\n"); is going off when I add the appropriate load do_speak.so in the Makefile, caml_startup is not going off correctly. Now I am calling caml_startup because if I don't then I get an error of
Makefile:9: dlopen(do_speak.so, 9): Symbol not found: _caml_atom_table
Referenced from: do_speak.so
Expected in: flat namespace
in do_speak.so
Makefile:9: *** do_speak.so: failed to load. Stop.
And this is because of the way that clang on OS X does linking, see here for more details: http://psellos.com/2014/10/2014.10.atom-table-undef.html
I am kind of out of ideas... I need to create a C shared library out of OCaml code which then needs to be part of another C shared library from which I obviously don't have the original argv pointers that caml_startup wants. As my code sample show, I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
I actually can't tell very well what you're asking. However, here's a comment on this part of your question:
I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
As far as I know, the only reason for the argv argument of caml_startup is to establish the command-line arguments (for Sys.argv). If you don't need command-line arguments it should be OK to call like this:
char *arg = NULL;
caml_startup(&arg);
Technically argv is supposed to contain at least one string (the name of the program). So maybe it would be better to call like this:
char *argv[] = { "program", NULL };
caml_startup(argv);
I'm try to override some libc function using LD_PRELOAD technique, but cannot make it work.
this is the strlib.c
#include <stdio.h>
size_t strlen(const char *s){
printf("take strlen for %s\n",s);
return 0;
}
gcc -shared -fPIC -o strlib.so strlib.c (.c file, no name mangle here)
and the main app
#include <string.h>
int main(){
const char* s = "hello";
printf("length=%d\n",strlen(s));
}
gcc -o main main.c
then start to run it
LD_PRELOAD=./strlib.so ./main
it run but seem that it did not call my override function
$ LD_PRELOAD=./strlib.so ./main
length=5
Did I do anything wrong here?
#edit: as Emest mention, a changed the main.c to avoid compiler optimize, but it still did not work.
#include <string.h>
int main(int argc,char** argv){
const char* s = "hello";
printf("length=%d\n",strlen(argv[1]));
}
$ LD_PRELOAD=./strlib.so ./main hehe
length=4
Check the assembly code ( use the -s argument to gcc.) The compiler will optimize out the strlen() call on the compile-time constant string "hello", computing the length at compile time instead. Try calling your function on a string whose length isn't known until runtime, like one of the arguments to main(), and this should work as you expect.