I am trying to write a file to SD card in spl_mmc.c. During compilation
gcc moans: undefined reference 'file_fat_write'. I don't understand why.
Directly after the (original) code in mmc_load_image_fat():
err = file_fat_read(payloadname,
(u8 *)spl_image.load_addr, 0);
I insert the following code:
file_fat_write("foo", "foo", 3);
Why doesn't gcc know this function as it is also declared in
include/fat.h just as file_fat_read() is?
Did someone manage to write to fat out of the SPL?
Best,
André
Related
(I am editing my initial post to add some more information)
I have recently moved to Julia because of its nice ability to create a binary out of the code.
While I followed this documentation I managed to create a binary.
Now, my intention is to pass an array to this binary. As it is mentioned in the documentation, one can pass arguments by using the global variable ARGS.
I am not sure how this could help in getting/returning an array.
To be more specific, I would like to:
write my algorithm in Julia (which gets an array, it does some calculations and returns a new array)
do the precompile
create the sysimage
create the shared library
and then call it in a similar way as in the documentation
EDIT: While the above seemed to be quite tricky, I thought I could follow the example here but simply creating my own module. That didn't work.
Here is what I tried:
I created the "my_test.jl"
module my_test
export real_main
export julia_main
function real_main(x::Float64, y::Float64)
println("from main " , x, " " , y)
end
Base.#ccallable function julia_main(x::Float64, y::Float64)::Cint
try
real_main(x,y)
return 0
catch
Base.invokelatest(Base.display_error, Base.catch_stack())
return 1
end
return 0
end
if abspath(PROGRAM_FILE) == #__FILE__
julia_main(3.,4.)
end
end
then I precompiled it, by using:
julia --startup-file=no --trace-compile=app_precompile.jl my_test.jl
Once the pre-compilation was successful, I created the create_sysimage.jl:
Base.init_depot_path()
Base.init_load_path()
#eval Module() begin
Base.include(#__MODULE__, "my_test.jl")
for (pkgid, mod) in Base.loaded_modules
if !(pkgid.name in ("Main", "Core", "Base"))
eval(#__MODULE__, :(const $(Symbol(mod)) = $mod))
end
end
for statement in readlines("app_precompile.jl")
try
Base.include_string(#__MODULE__, statement)
catch
# See julia issue #28808
Core.println("failed to compile statement: ", statement)
end
end
end # module
empty!(LOAD_PATH)
empty!(DEPOT_PATH)
Then, I built the shared library based on that image, in 2 steps:
julia --startup-file=no -J"$JULIA_DIR/lib/julia/sys.so" --output-o sys.o create_sysimage.jl
gcc -g -shared -o libsys.so -Wl,--whole-archive sys.o -Wl,--no-whole-archive -L"$JULIA_DIR/lib" -ljulia
Once this succeeds, I created the cpp file to use the library above. Therefore, my_test.cpp:
#include <julia.h>
JULIA_DEFINE_FAST_TLS()
int main()
{
libsupport_init();
jl_options.use_compiled_modules = JL_OPTIONS_USE_COMPILED_MODULES_YES;
jl_options.image_file = JULIAC_PROGRAM_LIBNAME;
jl_options.image_file_specified = 1;
jl_init_with_image(NULL,JULIAC_PROGRAM_LIBNAME);
//Enabling the below gives a better explanation of te failure
/*
jl_eval_string("using Main.my_test.jl");
if (jl_exception_occurred()) {
jl_call2(jl_get_function(jl_base_module, "showerror"),
jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
jl_atexit_hook(2);
exit(2);
}
jl_module_t* LA = (jl_module_t *)jl_eval_string("Main.my_test");
if (jl_exception_occurred()) {
jl_call2(jl_get_function(jl_base_module, "showerror"),
jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
jl_atexit_hook(3);
exit(3);
}
*/
jl_function_t *func1 = jl_get_function(jl_main_module, "julia_main");
if (jl_exception_occurred()) {
jl_call2(jl_get_function(jl_base_module, "showerror"),
jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
jl_atexit_hook(4);
exit(4);
}
jl_value_t* in1 = jl_box_float64(12.);
jl_value_t* in2 = jl_box_float64(24.);
jl_value_t* ret = NULL;
JL_GC_PUSH3(&in1,&in2,&ret);
ret = jl_call2(func1, in1, in2);
JL_GC_POP();
jl_atexit_hook(0);
}
And then compile it, as:
g++ -o pass_2_arrays_to_my_test_by_eval -fPIC -I$JULIA_DIR/include/julia -L$JULIA_DIR/lib -ljulia -L$CURRENT_FOLDER -lsys pass_2_arrays_to_my_test_by_eval.cpp $JULIA_DIR/lib/julia/libstdc++.so.6
The JULIA_DIR points to the Julia's installation directory and CURRENT_FOLDER points to the current working dir.
Calling the pass_2_arrays_to_my_test_by_eval fails with Segmentation Fault message.
To my understanding, it fails because it cannot load the module (you can see that if un-comment some lines in the cpp code).
Could someone give some help on that?
Some people in the past seem to do that without any issue (as here).
Thanks a lot in advance!
firstly, I have to say the dll was translated by MatLab's m file, which was compiled by c compiler using msvc_2015.
The dll was C shared library, which was said that has a common interface.
I don‘t think it's MatLab's error,because my program works.
The qt was compiled by MinGW_64_4.9.3 on my own computer,so i think qt's configuration is OK.
I can’t figure out why my program works OK, but debugging error, once I was using the fooInitialize(), there were a lot of segments error when debugging
QLibrary lib("foo.dll");
QMessageBox msg;
if(lib.load())
{
QMessageBox::information(NULL,"OK","DLL load is OK!");
Fun mlfFoo=(Fun)lib.resolve("mlfFoo"); //
Fun2 init=(Fun2)lib.resolve("fooInitialize");//
Fun2 termi=(Fun3)lib.resolve("fooTerminate");//
if (mlfFoo) //
{
QMessageBox::information(NULL,"OK","Link to Function is OK!");
init(); //
double numbrOut,*out;
double data[]={1};
mxArray* array_in,*array_out ;
array_in = mxCreateDoubleMatrix(1, 1, mxREAL);//
memcpy(mxGetPr(array_in),data , sizeof(double));
array_out=NULL;
mlfFoo(1, &array_out,array_in);
out=mxGetPr(array_out);
numbrOut=out[0];
mxDestroyArray(array_in); array_in=0;
mxDestroyArray(array_out); array_out = 0;
out=0;
if(numbrOut==10) QMessageBox::information(NULL,"NO","perfect!!!!");
termi();
}
else
QMessageBox::information(NULL,"NO","Linke to Function is not OK!!!!");
}
else
QMessageBox::information(NULL,"NO","DLL is not loaded!");`
I got this few minutes ago
"while parsing target library list: not well-formed (invalid token)"
"SuspendThread (tid=0x788) failed. (winerr 2)"
the dll's header file was made by matlab using msvc , I compared it to the samples in the matlab's document , it is the similar
Creating a simple server-client program using rpcgen.
I'm writing this .x file:
program REMOTE_PROG {
version MSG_RCV {
int STRLEN(string) = 1;
double SQUARE(double *) = 2;
int NUM_OF_DEV(int *) = 3;
} = 1;
} = 99;
executing with rpcgen file.x -> generates file_svc.c.
in the file_svc.c file, for some reason, it generates each function case with _svc extension:
case STRLEN:
xdr_argument = xdr_wrapstring;
xdr_result = xdr_int;
local = (char *(*)()) strlen_1_svc; //<--_SVC
break;
and when I try to compile the server after implementing the functions
int * strlen_1(char **, CLIENT *);
the compiler raises that error:
"_strlen_1_svc", referenced from:
_remote_prog_1 in file_svc-8501b7.o
ld: symbol(s) not found for architecture x86_64
But if I'll delete that auto generated _svc extension,local = (char *(*)()) strlen_1; //no _svc the program will compile successfully.
Why does this happen? why does the rpcgen adds the _svc extension to the functions and am I doing something wrong when I delete the _svc?
P.S same error also for square and num_of_dev functions, gave only strlen for example.
Thanks!
That's the convention, the _svc is short for service.
Your server needs to implement the service function, that is the strlen_1_svc function.
Your client calls the strlen_1 function. rpcgen + the RPC library does all the inbetween - it generates code for strlen_1 used by the client which will serialize the data and transfer it to the server, where an event loop dispatches the call to your code in the strlen_1_svc function.
After execution of rpcgen ex7.x you should have created the client and server stubs ex7_clnt.c and ex7_svc.c and also a header file ex7.h
In the header file you will have declared both functions strlen_1 and strlen_1_svc, they have to have different names as they are different functions: first one is on the client side and invokes the second one on the server side through RPC call.
the small example program below is giving me an assertion error ('settings != NULL' failed) and I can't understand why it thinks the settings structure pointer is NULL.
File test.c:
#include <fluidsynth.h>
int main(int argc, char** argv)
{
fluid_settings_t* settings = new_fluid_settings();
fluid_synth_setint(settings, "synth.polyphony", 128); //assertion error
delete_fluid_settings(settings);
return 0;
}
Compiled with: gcc test.c -lfluidsynth.
I've tried printing the address returned by new_fluid_settings() but it seems a valid address to me.
So I've searched through the fluidsynth 1.1.5 source code and find out the line 1213 of the file utils/fluid_settings.c :
fluid_return_val_if_fail (settings != NULL, 0);
But fluid_return_val_if_fail is just a simple macro for calling GLib's g_return_val_if_fail (utils/fluid_sys.h:59).
Since the settings address is a valid one, I can't think of something else. Isn't it true that NULL pointers point to the address 0x00?
Am I forgetting something important ?
Print the address before using it, using e.g. printf("the settings are at %p\n", settings);; and you can of course also add protection yourself:
if (settings != NULL)
{
fluid_synth_setint(settings, "synth.polyphony", 128);
}
If it's the _new() call that is failing, you need to dig into why that could happen, of course.
It used to be that you had to manually initialize the glib library that FluidSynth seems to depend on, but that should no longer be necessary.
I had a brief look, and it seems it tries to initialize a mutex inside the settings object (to make it thread-safe, I assume), so it's possible that you need to add a call to g_thread_init() to your main(), before the call to new_fluid_settings().
I'm trying to do a checkpoint/restart program in C and I'm studying cryoPID's code to see how a process can be restarted. In it's code, cryoPID creates the ELF header of the process to be restarted in a function that uses some global variable and it's really confusing.
I have been searching for an easy way to create an ELF executable file, even trying out libelf, but I find that most of the times some necessary information is vague in the documentation of these programs and I cannot get to understand how to do it. So any help in that matter would be great.
Seeing cryoPID's code I see that it does the whole creation in an easy way, not having to set all header fields, etc. But I cannot seem to understand the code that it uses.
First of all, in the function that creates the ELF the following code is relevant (it's in arch-x86_64/elfwriter.c):
Elf64_Ehdr *e;
Elf64_Shdr *s;
Elf64_Phdr *p;
char* strtab;
int i, j;
int got_it;
unsigned long cur_brk = 0;
e = (Elf64_Ehdr*)stub_start;
assert(e->e_shoff != 0);
assert(e->e_shentsize == sizeof(Elf64_Shdr));
assert(e->e_shstrndx != SHN_UNDEF);
s = (Elf64_Shdr*)(stub_start+(e->e_shoff+(e->e_shstrndx*e->e_shentsize)));
strtab = stub_start+s->sh_offset;
stub_start is a global variable defined with the macro declare_writer in cryopid.h:
#define declare_writer(s, x, desc) \
extern char *_binary_stub_##s##_start; \
extern int _binary_stub_##s##_size; \
struct stream_ops *stream_ops = &x; \
char *stub_start = (char*)&_binary_stub_##s##_start; \
long stub_size = (long)&_binary_stub_##s##_size
This macro is used in writer_*.c which are the files that implement writers for files. For example in writer_buffered.c, the macro is called with this code:
struct stream_ops buf_ops = {
.init = buf_init,
.read = buf_read,
.write = buf_write,
.finish = buf_finish,
.ftell = buf_ftell,
.dup2 = buf_dup2,
};
declare_writer(buffered, buf_ops, "Writes an output file with buffering");
So stub_start gets declared as an uninitialized global variable (the code above is not in any function) and seeing that all the variables in declare_writer are not set in any other part of the code, I assume that stub_start just point to some part of the .bss section, but it seems like cryoPID use it like it's pointing to its own ELF header.
Can anyone help me with this problem or assist me in anyway to create ELF headers easily?
As mentioned in the comment, it uses something similar to objcopy to set those variables (it doesn't use the objcopy command, but custom linkers that I think could be the ones that area "setting" the variables). Couldn't exactly find what, but I could reproduce the behavior by mmap'ing an executable file previously compiled and setting the variables stub_start and stub_size with that map.