Compilation error "Incomplete definition of type 'struct proc'" - c

We are trying to monitor the processes using the kauth process listener (KAUTH_SCOPE_PROCESS). One of the arguments for the kauth process listener is a pointer to proc_t (struct proc)
We want to access some of the members of proc_t, for example, p_name(process name), p_textvp (vnode of process executable) etc. We wrote a code however while compiling, we were getting compilation error "Incomplete definition of type 'struct proc'“
Would be appreciable if someone guides me to fix this.
static int ProcessScopeListener(
kauth_cred_t credential,
void* idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3
)
{
proc_t process = (proc_t) arg0;
…
//Compilation error in the following two lines
char* proc_name = &process->p_name[0];
struct vnode* p_textvp = process-> p_textvp;

.
.
.
return KERN_SUCESS;
}
Let me know if you need more information.

That struct is opaque, dereferencing pointers to it directly is not supported, as its layout may change from OS version to OS version.
Use the accessor functions such as proc_name() instead. Note that p_textvp is always NULL so there is no accessor.

Related

Accessing structure in structure through pointer

Brief description:
I write something to structure through pointer but something else gets written. I work in atollic true studio 8.1, programming an STM32F415RG MCU.
The strangest thing is that even if I look in variables and expression window, I can see the same structure with different values.
Same variable in two windows with different values
Now to elaborate a bit (I am going to simplify a lot of stuff to make it more readable).
I have my protocol handle type defined:
typedef struct
{
RS485DriverHandle master_rs485;
} EscomProtocolHandle;
My RS485 driver handle is defined as follows:
typedef struct
{
UART_HandleTypeDef* uart_handle;
TransceiverState transceiver_state;
GPIO_TypeDef* dir_gpio;
uint16_t dir_pin;
} RS485DriverHandle;
I have created my protocol handle as a global variable:
static EscomProtocolHandle hprot1;
I pass it to my protocol init function which takes a pointer to handle as an argument:
Escom_Protocol_Init(&hprot1);
Init function passes it to RS485 driver init function which takes pointer to RS485 handle as an argument (this call is simplified a lot):
void Escom_Protocol_Init(EscomProtocolHandle* protocol_handle)
{
RS485_Init(&protocol_handle->master_rs485)
}
RS485 init function sets default values:
void RS485_Init(RS485DriverHandle* rs485_handle, UART_HandleTypeDef* uart_handle,
GPIO_TypeDef* dir_gpio, uint16_t dir_pin)
{
/* default = listening */
rs485_handle->uart_handle = uart_handle;
rs485_handle->dir_gpio = dir_gpio;
rs485_handle->dir_pin = dir_pin;
ReceiverOutputEnable(rs485_handle);
rs485_handle->transceiver_state = kReceiving;
}
Now if I look at the local variable rs485_handle, the values are set correctly. But If I look at my handle hprot1, the values don't match. Even though rs485_handle's address matches the address of master_rs485 member of the hprot1 handle.
P.S.: I have not messed with the packing (#pragma pack) of any of the above mentioned structures, so that should not be an issue.
Got it!
There was a seemingly unrelated header file that had a structure prototype in it which was packed(1) and there was no #pragma pack() after the structre prototype to restore the packing to default state. Thus RS485DriverHandle was packed differently in different places. In both Escom_Protocol_Init and RS485_Init the address of the handle structure was the same, but the packing was different so for example the address of GPIO_TypeDef* dir_gpio member was 0x200000D6 in Escom_Protocol_Init but was 0x200000D9 in RS485_Init.

error: ‘struct tty_driver’ has no member named ‘write’

I am new to kernel module programming and got some problem while compiling some old kernel code. I am getting following error messages,
error: ‘struct tty_driver’ has no member named ‘write’
((my_tty->driver)->write) (my_tty,0,str,strlen(str));
I checked the tty_driver.h file, there write is defined. So, Whats going on? How can I access in version 3.13.0-24?
My code is here:
void print_string(char *str)
{
struct tty_struct *my_tty;
my_tty = get_current_tty();
if (my_tty != NULL)
{
(*(my_tty->driver)->write)(my_tty, 0, str, strlen(str));
}
}
Thanks in advance..
write is indeed defined, but not as members of tty_driver. It is defined as members of tty_operations, and tty_driver has a member ops, a pointer to a const tty_operations.
So, I used my_driver->ops->write instead of my_driver->driver->write.

keyboard interrupt handler giving null value

I am learning Linux Kernel Module programming(Interrupt Handler) and using the tutorial (http://tldp.org/LDP/lkmpg/2.6/html/) exact module link(http://tldp.org/LDP/lkmpg/2.6/html/x1256.html).
In the tutorial I am getting error when I used
INIT_WORK(&task, got_char, &scancode);
The error was "error: macro "INIT_WORK" passed 3 arguments, but takes just 2"
So I found one solution and use the below line
INIT_WORK(&task, got_char);
It's working fine but the output I am getting is null. I am expecting the key number from the keyboard.
Any body have any idea ?
If it is not clear please let me know I will try to interpret more.
Thanks
Add a structure like follows,
struct getchar_info {
/* Other info ... */
struct work_struct work;
unsigned int scancode;
/* Other info ... */
};
static struct getchar_info gci; /* Statically declare or use kmalloc() */
Change got_char() to,
static void got_char(struct work_struct *work)
{
struct getchar_info *info = container_of(work, struct getchar_info, work);
info->scancode = my_val;
/* ... */
Initialize it like INIT_WORK(&gci.work, got_char);
This is a common Linux kernel paradigm or design pattern. The work queue code needs to manage this structure pointer so it is easy to provide to your got_char routine. Your driver must allocate it as part of a larger structure (it is inheritence in OO terms; it looks like composition as 'C' only supports that). The container_of is like a C++ dynamic_cast<> (with single inheritance in case any C++ gurus are looking). It lets you get the composed structure from the sub-structure.

Array of structs - Array has incomplete element type (in C)

This seems like an easy problem to fix, but i'm doing something wrong. I've been through all the similar threads and didn't find anything that solved my problem, so any help would be appreciated!
Basically: C program, and i'm trying to create an array of bufferevents.
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
extern struct bufferevent bev[8];
//Then, my accept functions -- well, one of them...
static void accept1(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *address, int socklen,
void *ctx) {
/* A new connection was received on this port */
struct event_base *base = evconnlistener_get_base(listener);
bev[0] = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
/* Callback for when (*bufevent, data READ, data WRITTEN, event OCCURRED, *void) */
bufferevent_setcb(bev[0], read1, NULL, echo_event_cb, NULL);
}
When i attempt to compile (WITH -levent, i might add) i get this error:
src/mix/mix1.c:57:34: error: array type has incomplete element type
Any ideas? :(
Note: I am defining the bufferevents outside of main to make them accessible everywhere in my code without passing them. I have other #define's in the area, so i'm sure it's something to do with the way i'm building them??
struct bufferevent is only declared as an incomplete type in libevent's public headers; its contents are hidden to users of the public API. All the libevent functions that operate on bufferevents take a pointer to a bufferevent, so what you want here is
struct bufferevent *bev[8];
Note further that you do NOT want to put extern on that declaration or you'll get an undefined symbol error at link time. If it is only ever referred to in that file, you should use static instead. Otherwise there should be a declaration with extern in one of your application's header files in addition to the extern-less declaration in the file you showed.

Function pointers and callbacks in C

I have started to review callbacks. I found this link on SO:
What is a "callback" in C and how are they implemented? It has a good example of callback which is very similar to what we use at work. However, I have tried to get it to work, but I have many errors.
#include <stdio.h>
/* Is the actual function pointer? */
typedef void (*event_cb_t)(const struct event *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
int event_cb_register(event_ct_t cb, void *user_data);
static void my_event_cb(const struct event *evt, void *data)
{
/* do some stuff */
}
int main(void)
{
event_cb_register(my_event_cb, &my_custom_data);
struct event_cb *callback;
callback->cb(event, callback->data);
return 0;
}
I know that callbacks use function pointers to store an address of a function. But there are a few things that I find I don't understand:
What is meant by "registering the callback" and "event dispatcher"?
This code compiles and runs under GCC with -Wall.
#include <stdio.h>
struct event_cb;
typedef void (*event_cb_t)(const struct event_cb *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
static struct event_cb saved = { 0, 0 };
void event_cb_register(event_cb_t cb, void *user_data)
{
saved.cb = cb;
saved.data = user_data;
}
static void my_event_cb(const struct event_cb *evt, void *data)
{
printf("in %s\n", __func__);
printf("data1: %s\n", (const char *)data);
printf("data2: %s\n", (const char *)evt->data);
}
int main(void)
{
char my_custom_data[40] = "Hello!";
event_cb_register(my_event_cb, my_custom_data);
saved.cb(&saved, saved.data);
return 0;
}
You probably need to review whether the call back function gets the whole struct event_cb or not - usually, you'd just pass the data because, as demonstrated, otherwise you have two sources of the same information (and a spare copy of the pointer to the function that you're in). There is a lot of cleanup that can be done on this - but it does work.
A question in the comments asks: Is this a good example of a callback?
Succinctly, no - but in part because there isn't sufficient infrastructure here.
In a sense, you can think of the comparison function passed to the qsort() or bsearch() functions as a callback. It is a pointer to a function that is passed into the generic function that does what the generic function cannot do for itself.
Another example of a callback is a signal handler function. You tell the system to call your function when the event - a signal - occurs. You set up the mechanisms ahead of time so that when the system needs to call a function, it knows which function to call.
The example code is attempting to provide a more elaborate mechanism - a callback with a context. In C++, this would perhaps be a functor.
Some of the code I work with has very fussy requirements about memory management - when used in a particular context. So, for testing, I use malloc() et al, but in production, I have to set the memory allocators to the specialized allocators. Then I provide a function call in the package so that the fussy code can override the default memory allocators with its own surrogate versions - and provided the surrogates work OK, the code will behave as before. Those are a form of callback - again, a form that does not need much (or anything) in the way of user context data.
Windowing systems have event handlers (callbacks) that are registered and that the GUI main event loop will call when events occur. Those usually need user context as well as the event-specific information provided by the GUI system.
What is meant by "registering the callback" and "event dispatcher"?
"registering the callback" is the act of telling the underlying system which precise function to call, and (optionally) with which parameters, and possibly also for which particular class of events that callback should be invoked.
The "event dispatcher" receives events from the O/S (or GUI, etc), and actually invokes the callbacks, by looking in the list of registered callbacks to see which are interested in that event.
Without the compiler output it's hard, but I can see a few problems;
int event_cb_register(event_ct_t cb, void *user_data);
Should be
int event_cb_register(event_cb_t cb, void *user_data);
The my_custom_data variable does not exist when it's used here;
event_cb_register(my_event_cb, &my_custom_data);
This pointer is never initialized;
struct event_cb *callback;
And in;
callback->cb(event, callback->data);
You cannot pass the name of a type ('event') to a function, you must pass an instance of that type.
int event_cb_register(event_ct_t cb, void *user_data);
What is that type event_ct_t? Do you mean event_cb_t?
struct event_cb *callback;
Creates an uninitialized pointer to a structure event_cb. Note mostly this points to garbage.
callback->cb(event, callback->data);
You are trying to call garbage. You need initialization:
struct event_cb callback;
callback.cb = my_event_cb;
callback.data = 42;
or some such stuff.
Registering a callback means that you are specifying which function should be called when the event of interest occurs. Basically you are setting the function pointer when registering a callback.
You created a pointer of the struct you declared, but it does not point to anything:
struct event_cb *callback;
You should just create a type of your struct:
struct event_cb callback;
and then pass its address to the functions.

Resources