I have been trying to modify a piece of code in likewise-open and am totally stumped here.
Some background
Working on this file, trying to code around some LDAP queries:
typedef void *MYH;
typedef MYH HANDLE;
HANDLE hDirectory = NULL;
hDirectory = LsaDmpGetLdapHandle(pConn);
The LsaDmpGetLdapHandle() is defined here
typedef void *MYH;
typedef MYH HANDLE;
HANDLE
LsaDmpGetLdapHandle(
IN PLSA_DM_LDAP_CONNECTION pConn
)
{
return pConn->hLdapConnection;
}
where PLSA_DM_LDAP_CONNECTION is typedef for following struct:
struct _LSA_DM_LDAP_CONNECTION
{
...
// NULL if not connected
HANDLE hLdapConnection;
...
};
Basically, there is HANDLE type everywhere.
Note: Just to avoid various *.h files defining it differently, I added that typedef void *MYH; in both files
The trouble:
The code would crash after the line where hDirectory is assigned from what is returned by LsaDmpGetLdapHandle and I try to further use hDirectory
What I have debugged, till now:
Attaching gdb, hLdapConnection in pConn is:
(gdb) p pConn->hLdapConnection
$5 = (void *) 0x7feb939d6390
However, hDirectory is:
(gdb) p hDirectory
$6 = (void *) 0xffffffff939d6390
I fail to understand why the difference, after assignment ??
Also, to note, the 939d6390 in both the pointer addresses is common.
Interestingly, both of these approaches work
// If I pass hDirectory reference
LsaDmLdapGetHandle(pConn, &hDirectory);
// where this function is defined as, in the other file:
DWORD
LsaDmLdapGetHandle(
IN PLSA_DM_LDAP_CONNECTION pConn,
OUT HANDLE* phDirectory)
{
HANDLE hDirectory = NULL;
hDirectory = LsaDmpGetLdapHandle(pConn);
*phDirectory = hDirectory;
return ERROR_SUCCESS;
}
// Or I call another function, which then call LsaDmpGetLdapHandle(), in the other file
hDirectory = LsaDmLdapGetHandleCopy(pConn);
HANDLE
LsaDmLdapGetHandleCopy(
IN PLSA_DM_LDAP_CONNECTION pConn)
{
HANDLE hDirectory = NULL;
hDirectory = LsaDmpGetLdapHandle(pConn);
return hDirectory;
}
I thought, maybe something to do with HANDLE definitions being different in those 2 files, hence I added my own void * definitions in both files
Looks like dup of this
By default all return values are int. So if a prototype is missing for function then compiler treats the return value as 32-bit and generates code for 32-bit return value. Thats when your upper 4 bytes gets truncated.
Related
I hit weird case when trying to call c from ocaml.
This is the c side of things:
typedef struct {
TSNode node;
} AstNode;
CAMLprim value caml_ts_document_root_node(value document) {
CAMLparam1(document);
TSNode root_node = ts_document_root_node(document);
AstNode elNode;
elNode.node = root_node;
CAMLreturn(&elNode);
}
CAMLprim value caml_ts_node_string(value node) {
CAMLparam1(node)
CAMLlocal1(mls);
AstNode* n = (AstNode*) node;
char *s = ts_node_string(n->node);
mls = caml_copy_string(s);
CAMLreturn(mls);
}
On the ocaml side
type ts_point
type ts_document
external ts_node_string : ts_node -> string = "caml_ts_node_string"
external ts_document_root_node : ts_document -> ts_node = "caml_ts_document_root_node"
If you see the code, I'm wrapping in caml_ts_document_root_node the TSNode root_node = ts_document_root_node(document); in an extra defined struct AstNode.
When I write the following implementation however:
CAMLprim value caml_ts_document_root_node(value document) {
CAMLparam1(document);
TSNode root_node = ts_document_root_node(document);
CAMLreturn(&root_node);
}
My code segfaults when calling caml_ts_node_string on the returned node by caml_ts_document_root_node.
Does anyone have any hints on why the segfault appears when I don't wrap a TSNode in an extra struct when interoping from ocaml?
That's definitely not the right usage of the foreign interface! You can't just take a value and cast it to OCaml value. OCaml values are specially encoded, even integers, and have a different representation than C values.
If you want to encode a C value as an OCaml value, you shall use custom values.
First of all, you need to implement the interface of a custom value, fortunately, you can rely on defaults for that:
static struct custom_operations ast_ops = {
"ast_node",
custom_finalize_default
custom_compare_default,
custom_hash_default,
custom_serialize_default,
custom_deserialize_default,
custom_compare_ext_default
};
Next, you need to learn how to allocate custom blocks. For example, the following call will allocate the new AstNode in the OCaml heap:
res = caml_alloc_custom(&ast_ops, sizeof(AstNode), 0, 1);
To access the value itself, you need to use the Data_custom_val macro, e.g.,
if (res) {
AstNode *node = Data_custom_val(res);
TsNode *tsnode = res->node;
}
The complete example of a correct (I hope) implementation of your first function is below:
CAMLprim value caml_ts_document_root_node(value document) {
CAMLparam1(document);
CAMLlocal1(res);
res = caml_alloc_custom(&ast_ops, sizeof(AstNodes), 0, 1);
if (res) {
AstNode *ast = (AstNode *)Data_custom_val(res);
ast->node = ts_document_root_node(document);
}
CAMLreturn(res);
}
As you may see, this is not trivial and rather low-level. Though nothing really magical, especially after you've read the corresponding parts of the OCaml documentation. However, it is much easier to use the CTypes library, that hides most of those complexities and allows you to call C function directly from OCaml
This seems to be unrelated to the ocaml interop part; you are returning the address of a local variable in this function:
CAMLprim value caml_ts_document_root_node(value document) {
// ...
AstNode elNode;
// ...
CAMLreturn(&elNode);
}
When it returns, the (stack) memory it refers to is invalid (in the sense that it will be reused at the next function call).
Ive been dabbling in some c code and initialized a cat structure like so
typedef struct
{
int age;
char *name;
char *favoriteQuote;
} Cat;
I created two functions, one to initialize the cat object and one to zero out the memory that look like so
Cat initialize_cat_object(void)
{
Cat my_cat;
my_cat.age = 3;
my_cat.favorite_quote = "A day without laughter is a day wasted";
my_cat.name = "Chester";
return my_cat;
}
Cat destroy_cat_object(void)
{
Cat my_cat;
memset(&my_cat, 0, sizeof(my_cat));
//--forgot to return 'my_cat' here--
}
my main function looks like so
void main(void)
{
Cat my_cat;
my_cat = initialize_cat_object();
printf("Creating cat\n")
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
my_cat = destroy_cat_obect();
printf("CAT DESTRUCTION\n");
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
}
The output of the program was the expected output of
It wasn't until I went back to the source code that I noticed I had forgotten to return the Cat object who's memory was zeroed out, However the program still shows the expected output, but if I try to omit the return statement of the 'initialize_cat_object' function, the output of the data is corrupt
The only thing I can think of is that 'destroy_cat_object' returns the zeroed out memory, but how could this be?
destroy_cat_object doesn't have a return statement. C11 6.9.1p12 says:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
It is however perfectly OK C-standard-wise to have a function with a return type but which doesn't have a return statement before the closing bracket. Calling such a function is also perfectly OK.
What is not OK however is using the return value of the function call if the function didn't terminate with a return statement that explicitly returns a value.
You might want to enable some extra diagnostics in your compiler settings if you do not get a message for this.
Registers aside. There are three places where your data may be stored in C:
Constant data which is read only and is stored inside your binary;
Data on the stack;
Data stored in dynamic memory retrieved by the means of memory allocation functions.
In your case we are talking about stack. Stack is a LIFO queue elements of which are valid and accessible so long as they are not popped out of it. So if you have a function like this:
typedef struct {
int a_val;
float b_val;
char c_val;
} a_t;
a_t* func(void) {
a_t a = {1, 1., 'a'};
return &a;
}
"a" would be residing in stack until func returns, hence after func returns it's pointer becomes invalid and points someplace in stackspace. On the most systems stack won't be zeroed therefore until some other data overwrites it it may be possible to get some data by that pointer, which may be misleading.
So what should you do? Something like this:
void initialize_cat(Cat*);
void clear_cat(Cat*);
int main() {
Cat my_cat;
initialize_cat(&my_cat);
// do kitty stuff
clear_cat(&my_cat); // cat's private data must not be compromised
}
When function returns a structure this is actually achieved with a cooperation from a caller (I'm talking SysV x64 ABI here and may be wrong for other cases). Basically caller allocates space on stack enough to store the returned structure and passes pointer to it as an implicit first parameter. callee is using this pointer to write data later on.
So the two cases:
Cat callee(void) {
Cat my_cat = { .age = 5 };
return cat;
}
void caller(void) {
Cat my_cat = callee();
}
And:
void callee(Cat *my_cat) {
my_cat->age = 5;
return cat;
}
void caller(void) {
Cat my_cat;
callee(&my_cat);
}
Are pretty much the same.
This is really weird.
I have a struct with int variable a = 0 defined in a Manager.h file, instantiated in Manager.c. The manager runs a function pointer during execution time, defined in main.c. However, after running, a = 10.
Anyone knows why this is so? To illustrate:
**Manager.h**
struct Manager {
uint32_t a;
};
runFunction (void (* handler)());
**Manager.c**
struct Manager * manager = calloc(sizeof(struct Manager));
// ...
**main.c**
void someFn() {
// do stuff...
}
int main() {
runFunction(someFn);
// and manager->a becomes 10. Previously, it was initialized to 0.
}
The code you are showing misses one important point: it most likely didn't transport the error.
I am passing queues like these between source files a.c and b.c
File : a.c
sq[a]=new_queue();
pthread_create(&st[a],NULL,sendPacket,sq[a]);
File : b.c
void *sendPacket(void *queue){
/* here i need to know which queue has come ,determine
the index of queue how can I do it? */
}
Create a more high-level representation of your queue. It seems the queue can be a void * (you're not showing its actual type, i.e. what does the new_queue() call return?), so embed that in a structure while adding the additional parameters:
struct queue_state {
void *queue;
int index;
};
Then instantiate a structure, and pass a pointer to it to the thread function:
struct queue_state qsa = malloc(sizeof *qsa);
if(qsa != NULL)
{
qsa->queue = new_queue();
qsa->index = 4711; /* or whatever */
pthread_create(&st[a], NULL, sendPacket, qsa);
}
Then the thread function can use the struct declaration to access all the fields. Of course, the declaration needs to be in a shared header (say queue.h) which is included from both C files.
Your question description is very rough. But at least from what I understand, you actually need to pass 2 parameters to your function: the (pointer to) queue (which seems an array for me), and the index within this queue.
You may not pack both your parameters in a single variable of type void*. What you may do is declare a struct with all the needed parameters, fill it, and pass a pointer to it to your thread.
Like this (error handling omitted):
struct Params
{
queue* m_Queue;
size_t m_Idx;
};
// ...
Params* pParams = new Params;
pParams->m_Queue = sq;
pParams->m_Idx = a;
pthread_create(&st[a],NULL,sendPacket, pParams);
void *sendPacket(void *pPtr)
{
Params* pParams = (Params*) pPtr;
// ...
delete pParams;
}
Probably it is easier if you just pass the index to the function:
void *sendPacket(int queue_idx) {
queue_t *queue = &sq[queue_idx];
}
If in b.c you have access to sq, you can just pass the index to the queue. Otherwise you can pass a struct containing the actual queue and the index
I am working on an embedded application where the device is controlled through a command interface. I mocked the command dispatcher in VC and had it working to my satisfaction; but when I then moved the code over to the embedded environment, I found out that the compiler has a broken implementation of pointer-to-func's.
Here's how I originally implemented the code (in VC):
/* Relevant parts of header file */
typedef struct command {
const char *code;
void *set_dispatcher;
void *get_dispatcher;
const char *_description;
} command_t;
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, &set_##dispatcher, &get_##dispatcher, (const char*)description}
/* Dispatcher data structure in the C file */
const command_t commands[] = {
COMMAND_ENTRY("DH", Dhcp, "DHCP (0=off, 1=on)"),
COMMAND_ENTRY("IP", Ip, "IP Address (192.168.1.205)"),
COMMAND_ENTRY("SM", Subnet, "Subunet Mask (255.255.255.0)"),
COMMAND_ENTRY("DR", DefaultRoute, "Default router (192.168.1.1)"),
COMMAND_ENTRY("UN", Username, "Web username"),
COMMAND_ENTRY("PW", Password, "Web password"),
...
}
/* After matching the received command string to the command "label", the command is dispatched */
if (pc->isGetter)
return ((get_fn_t)(commands[i].get_dispatcher))(pc);
else
return ((set_fn_t)(commands[i].set_dispatcher))(pc);
}
Without the use of function pointers, it seems like my only hope is to use switch()/case statements to call functions. But I'd like to avoid having to manually maintain a large switch() statement.
What I was thinking of doing is moving all the COMMAND_ENTRY lines into a separate include file. Then wraps that include file with varying #define and #undefines. Something like:
/* Create enum's labels */
#define COMMAND_ENTRY(label,dispatcher,description) SET_##dispatcher, GET_##dispatcher
typedef enum command_labels = {
#include "entries.cinc"
DUMMY_ENUM_ENTRY} command_labels_t;
#undefine COMMAND_ENTRY
/* Create command mapping table */
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, SET_##dispatcher, GET_##dispatcher, (const char*)description}
const command_t commands[] = {
#include "entries.cinc"
NULL /* dummy */ };
#undefine COMMAND_ENTRY
/*...*/
int command_dispatcher(command_labels_t dispatcher_id) {
/* Create dispatcher switch statement */
#define COMMAND_ENTRY(label,dispatcher,description) case SET_##dispatcher: return set_##dispatcher(pc); case GET_##dispatcher: return get_##dispatcher(pc);
switch(dispatcher_id) {
#include "entries.cinc"
default:
return NOT_FOUND;
}
#undefine COMMAND_ENTRY
}
Does anyone see a better way to handle this situation? Sadly, 'get another compiler' is not a viable option. :(
--- Edit to add:
Just to clarify, the particular embedded environment is broken in that the compiler is supposed to create a "function-pointer table" which is then used by the compiler to resolve calls to functions through a pointer. Unfortunately, the compiler is broken and doesn't generate a correct function-table.
So I don't have an easy way to extract the func address to invoke it.
--- Edit #2:
Ah, yes, the use of void *(set|get)_dispatcher was my attempt to see if the problem was with the typedefine of the func pointers. Originally, I had
typedef int (*set_fn_t)(cmdContext_t *pCmdCtx);
typedef int (*get_fn_t)(cmdContext_t *pCmdCtx);
typedef struct command {
const char *code;
set_fn_t set_dispatcher;
get_fn_t get_dispatcher;
const char *_description;
} command_t;
You should try changing your struct command so the function pointers have the actual type:
typedef struct command {
const char *code;
set_fn_t set_dispatcher;
get_fn_t get_dispatcher;
const char *_description;
} command_t;
Unfortunately, function pointers are not guaranteed to be able to convert to/from void pointers (that applies only to pointers to objects).
What's the embedded environment?
Given the information posted in the updates to the question, I see that it's really a bugged compiler.
I think that your proposed solution seems pretty reasonable - it's probably similar to what I would have come up with.
A function pointer isn't actually required to fit in a void*. You could check to make sure that the value you're calling is actually the address of the function. If not, use a function pointer type in the struct: either get_fn_t, or IIRC void(*)(void) is guaranteed to be compatible with any function pointer type.
Edit: OK, assuming that calling by value can't be made to work, I can't think of a neater way to do what you need than auto-generating the switch statement. You could maybe use an off-the-shelf ASP-style preprocessor mode for ruby/python/perl/php/whatever prior to the C preprocessor. Something like this:
switch(dispatcher_id) {
<% for c in commands %>
case SET_<% c.dispatcher %>: return set_<% c.dispatcher %>(pc);
case GET_<% c.dispatcher %>: return get_<% c.dispatcher %>(pc);
<% end %>
default:
return NOT_FOUND;
}
might be a bit more readable than the macro/include trick, but introducing a new tool and setting up the makefiles is probably not worth it for such a small amount of code. And the line numbers in the debug info won't relate to the file you think of as the source file unless you do extra work in your preprocessor to specify them.
Can you get the vendor to fix the compiler?
To what extent is the pointer-to-function broken?
If the compiler allows you to get the address of a function (I'm from C++, but &getenv is what I mean), you could wrap the calling convention stuff into assembler.
As said, I'm a C++ssie, but something in the way of
; function call
push [arg1]
push [arg2]
call [command+8] ; at the 4th location, the setter is stored
ret
If even that is broken, you could define an array of extern void* pointers which you define, again, in assembly.
try this syntax:
return (*((get_fn_t)commands[i].get_dispatcher))(pc);
It's been awhile since I've done C & function pointers, but I believe the original C syntax required the * when dereferencing function pointers but most compilers would let you get away without it.
Do you have access to the link map?
If so, maybe you can hack your way around the wonky function-pointer table:
unsigned long addr_get_dhcp = 0x1111111;
unsigned long addr_set_dhcp = 0x2222222; //make these unique numbers.
/* Relevant parts of header file */
typedef struct command {
const char *code;
unsigned long set_dispatcher;
unsigned long get_dispatcher;
const char *_description;
} command_t;
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label,
addr_set_##dispatcher, addr_get_##dispatcher, (const char*)description}
Now compile, grab the relevant addresses from the link map, replace the constants, and recompile. Nothing should move, so the map ought to stay the same. (Making the original constants unique should prevent the compiler from collapsing identical values into one storage location. You may need a long long, depending on the architecture)
If the concept works, you could probably add a post-link step running a script to do the replacement automagically. Of course, this is just a theory, it may fail miserably.
Maybe, you need to look into the structure again:
typedef struct command {
const char *code;
void *set_dispatcher; //IMO, it does not look like a function pointer...
void *get_dispatcher; //more like a pointer to void
const char *_description;
} command_t;
Let say your dispatchers have the following similar function definition:
//a function pointer type definition
typedef int (*genericDispatcher)(int data);
Assume that the dispatchers are like below:
int set_DhcpDispatcher(int data) { return data; }
int get_DhcpDispatcher(int data) { return 2*data; }
So, the revised structure will be:
typedef struct command {
const char *code;
genericDispatcher set_dispatcher;
genericDispatcher get_dispatcher;
const char *_description;
} command_t;
Your macro will be:
#define COMMAND_ENTRY(label,dispatcher,description) \
{ (const char*)label, \
set_##dispatcher##Dispatcher, \
get_##dispatcher##Dispatcher, \
(const char*)description }
Then, you can set your array as usual:
int main(int argc, char **argv)
{
int value1 = 0, value2 = 0;
const command_t commands[] = {
COMMAND_ENTRY("DH", Dhcp, "DHCP (0=off, 1=on)")
};
value1 = commands[0].set_dispatcher(1);
value2 = commands[0].get_dispatcher(2);
printf("value1 = %d, value2 = %d", value1, value2);
return 0;
}
Correct me, if I am wrong somewhere... ;)