In a library I use, there is a WriteCallback type. I don't know what is it, I cannot find it define anywhere ?
Could someone explain me what is WriteCallback ? Is it a native function or type in c++ ?
.h file
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WConstants.h"
#endif
typedef void (*WriteCallback) (const byte what); // send a byte to serial port
typedef int (*AvailableCallback) (); // return number of bytes available
typedef int (*ReadCallback) (); // read a byte from serial port
void sendMsg (WriteCallback fSend,
const byte * data, const byte length);
byte recvMsg (AvailableCallback fAvailable, ReadCallback fRead,
byte * data, const byte length,
unsigned long timeout = 500);
typedef void (*WriteCallback) (const byte what); defines a function pointer type which takes a const byte and returns a void. It is used to easily use function pointers. Just as uint8_t is defined using a typedef as: typedef unsigned char uint8_t; to be used as a easy shorthand for a 8bit width variable.
A example usage would be:
typedef void (*WriteCallback) (const byte what);
void sendMsg (WriteCallback fSend, const byte * data, const byte length);
void callbackfunction(const byte what) { /*do stuff*/ }
With a function call:
sendMsg(&callbackfunction,0);
Internally the sendMsg would call the function pointed to by the fSend variable which in this case is callbackfunction.
The usage of this typedef makes it possbile to easily define pointers to functions and as per example switch the used write callback.
Writecallback funcPtr;
void switchCallback(){
static int tmp = 0;
if(tmp)
funcPtr = &writecallbackA;
else
funcPtr = &writecallbackB;
tmp = (tmp) ? 0 : 1;
}
The above usage is more easily readable and comprehendeable than:
void (*fun_ptr) (const byte what);
Related
In a kernel module, how to list all the kernel symbols with their addresses?
The kernel should not be re-compiled.
I know "cat /proc/kallsyms" in an interface, but how to get them directly from kernel data structures, using functions like kallsyms_lookup_name.
Example
Working module code:
#include <linux/module.h>
#include <linux/kallsyms.h>
static int prsyms_print_symbol(void *data, const char *namebuf,
struct module *module, unsigned long address)
{
pr_info("### %lx\t%s\n", address, namebuf);
return 0;
}
static int __init prsyms_init(void)
{
kallsyms_on_each_symbol(prsyms_print_symbol, NULL);
return 0;
}
static void __exit prsyms_exit(void)
{
}
module_init(prsyms_init);
module_exit(prsyms_exit);
MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Module for printing all kernel symbols");
MODULE_LICENSE("GPL");
Explanation
kernel/kallsyms.c implements /proc/kallsyms. Some of its functions are available for external usage. They are exported via EXPORT_SYMBOL_GPL() macro. Yes, your module should have GPL license to use it. Those functions are:
kallsyms_lookup_name()
kallsyms_on_each_symbol()
sprint_symbol()
sprint_symbol_no_offset()
To use those functions, include <linux/kallsyms.h> in your module. It should be mentioned that CONFIG_KALLSYMS must be enabled (=y) in your kernel configuration.
To print all the symbols you obviously have to use kallsyms_on_each_symbol() function. The documentation says next about it:
/* Call a function on each kallsyms symbol in the core kernel */
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
unsigned long), void *data);
where fn is your callback function that should be called for each symbol found, and data is a pointer to some private data of yours (will be passed as first parameter to your callback function).
Callback function must have next signature:
int fn(void *data, const char *namebuf, struct module *module,
unsigned long address);
This function will be called for each kernel symbol with next parameters:
data: will contain pointer to your private data you passed as last argument to kallsyms_on_each_symbol()
namebuf: will contain name of current kernel symbol
module: will always be NULL, just ignore that
address: will contain address of current kernel symbol
Return value should always be 0 (on non-zero return value the iteration through symbols will be interrupted).
Supplemental
Answering the questions in your comment.
Also, is there a way to output the size of each function?
Yes, you can use sprint_symbol() function I mentioned above to do that. It will print symbol information in next format:
symbol_name+offset/size [module_name]
Example:
psmouse_poll+0x0/0x30 [psmouse]
Module name part can be omitted if symbol is built-in.
I tried the module and see the result with "dmesg". But a lot of symbols are missing such as "futex_requeue". The output symbol number is about 10K, while it is 100K when I use "nm vmlinux".
This is most likely because your printk buffer size is insufficient to store all the output of module above.
Let's improve above module a bit, so it provides symbols information via miscdevice. Also let's add function size to the output, as requested. The code as follows:
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/sizes.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#define DEVICE_NAME "prsyms2"
/* 16 MiB is sufficient to store information about approx. 200K symbols */
#define SYMBOLS_BUF_SIZE SZ_16M
struct symbols {
char *buf;
size_t pos;
};
static struct symbols symbols;
/* ---- misc char device definitions ---- */
static ssize_t prsyms2_read(struct file *file, char __user *buf, size_t count,
loff_t *pos)
{
return simple_read_from_buffer(buf, count, pos, symbols.buf,
symbols.pos);
}
static const struct file_operations prsyms2_fops = {
.owner = THIS_MODULE,
.read = prsyms2_read,
};
static struct miscdevice prsyms2_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &prsyms2_fops,
};
/* ---- module init/exit definitions ---- */
static int prsyms2_store_symbol(void *data, const char *namebuf,
struct module *module, unsigned long address)
{
struct symbols *s = data;
int count;
/* Append address of current symbol */
count = sprintf(s->buf + s->pos, "%lx\t", address);
s->pos += count;
/* Append name, offset, size and module name of current symbol */
count = sprint_symbol(s->buf + s->pos, address);
s->pos += count;
s->buf[s->pos++] = '\n';
if (s->pos >= SYMBOLS_BUF_SIZE)
return -ENOMEM;
return 0;
}
static int __init prsyms2_init(void)
{
int ret;
ret = misc_register(&prsyms2_misc);
if (ret)
return ret;
symbols.pos = 0;
symbols.buf = vmalloc(SYMBOLS_BUF_SIZE);
if (symbols.buf == NULL) {
ret = -ENOMEM;
goto err1;
}
dev_info(prsyms2_misc.this_device, "Populating symbols buffer...\n");
ret = kallsyms_on_each_symbol(prsyms2_store_symbol, &symbols);
if (ret != 0) {
ret = -EINVAL;
goto err2;
}
symbols.buf[symbols.pos] = '\0';
dev_info(prsyms2_misc.this_device, "Symbols buffer is ready!\n");
return 0;
err2:
vfree(symbols.buf);
err1:
misc_deregister(&prsyms2_misc);
return ret;
}
static void __exit prsyms2_exit(void)
{
vfree(symbols.buf);
misc_deregister(&prsyms2_misc);
}
module_init(prsyms2_init);
module_exit(prsyms2_exit);
MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Module for printing all kernel symbols");
MODULE_LICENSE("GPL");
And here is how to use it:
$ sudo insmod prsyms2.ko
$ sudo cat /dev/prsyms2 >symbols.txt
$ wc -l symbols.txt
$ sudo rmmod prsyms2
File symbols.txt will contain all kernel symbols (both built-in and from loaded modules) in next format:
ffffffffc01dc0d0 psmouse_poll+0x0/0x30 [psmouse]
It seems that I can use kallsyms_lookup_name() to find the address of the function, can then use a function pointer to call the function?
Yes, you can. If I recall correctly, it's called reflection. Below is an example how to do so:
typedef int (*custom_print)(const char *fmt, ...);
custom_print my_print;
my_print = (custom_print)kallsyms_lookup_name("printk");
if (my_print == 0) {
pr_err("Unable to find printk\n");
return -EINVAL;
}
my_print(KERN_INFO "### printk found!\n");
I want to use the write sycall for copying a struct
from userspace to kernel.
In both user and kernel space, the struct is defined as
struct packet{
unsigned char packet[256];
int length;
}__attribute__ ((packed));
User space uses a local variable of type struct packet and passes it to the write syscall.
struct packet p;
/* ... (fill in data) */
printf("packet.length: %d\n",packet.length); /* looks correct */
result = write(uartFD, &p, sizeof(struct packet));
The kernel side looks like this, checking for correct length is done, just removed from example.
/* write syscall */
ssize_t packet_write(
struct file *file_ptr,
const char __user *user_buffer,
size_t count, loff_t *position)
{
struct packet p;
int retval;
if (copy_from_user((void*)&p, user_buffer, sizeof(struct packet))){
retval = -EACCES;
goto err;
}
/* looks wrong - different numbers like 96373062 or 96373958 */
printk("packet length: %d\n",p.length);
The opposite direction using read sycall is working as expected:
/* read syscall */
struct packet p;
/* ... (fill in data) */
copy_to_user(user_buffer, (void*)&p, sizeof(struct packet));
/* userspace */
read(uartFD, (void*)&packet, sizeof(struct packet));
What am I doing wrong with write syscall?
(Posted on behalf of the OP).
This is solved - it was my own silly. Both copying an integer and an unsigned char buffer separately was working, so it had to be something about the struct.
One site was packed, the other was not... reusing old code...
I am trying to write a simple matrix operations API using go and expose the APIs as a shared library. This shared library will be used from Java(using JNA) and from C.
The documentation is very sparse about using any data type beyond simple int or string as function parameters.
My requirement is to expose functions with 1 or more 2D slices as parameters AND also as return types. I am not able to figure out if such a thing is supported.
Is this possible? Are there any examples for this?
I think the key point is to have a look to the c bindings of slice,string and int generated by go build tool. I not tried 2D slice, but it should no different to 1D slice with unsafe pointer converter, maybe just be one more time allocation and convertion.
I'm not sure it's the best way, but here's the example for 1D slice:
the go part:
import "C"
//export CFoo
func CFoo(content []byte) string{
var ret []byte
//blablabla to get ret
cbuf := unsafe.Pointer(C.malloc(C.size_t(len(ret))))
C.memcpy(cbuf, unsafe.Pointer(&ret[0]), C.size_t(len(ret)))
var finalString string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&finalString))
hdr.Data = uintptr(unsafe.Pointer(cbuf))
hdr.Len = len(ret)
return finalString
}
compile with -buildmode=c-shared, to get libmygo.so.
I not know JNA, expecting it like JNI. the JNI part as well as pure C part:
#include <stdio.h>
#include <jni.h>
#include <string.h>
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
JNIEXPORT JNICALL jbyteArray Java_com_mynextev_infotainment_app_myev_Native_foo(JNIEnv* env, jobject obj,jbyteArray content){
JNIEnv ienv = *env;
void * Ccontent = ienv->GetByteArrayElements(env, content, 0);
int Lcontent = ienv->GetArrayLength(env, content);
GoSlice Gcontent = {Ccontent, Lcontent, Lcontent};
if(!gret.n){
printf("jni CDoAESEnc");
return NULL;
}
jbyteArray ret = ienv->NewByteArray(env, gret.n);
ienv->SetByteArrayRegion(env, ret, 0, gret.n, gret.p);
free((void*)gret.p);
ienv->ReleaseByteArrayElements(env, content, Ccontent, JNI_ABORT);
return ret;
}
build it with libmygo.so.
finally you get two so files. one for C which can be used standalone; one for Java which must be used with libmygo.so together.
I use the following C structs in my C++11 code (the code comes from liblwgeom of PostGis, but this is not the core of the question). The code is compiled with the following options using g++-4.8:
-std=c++11 -Wall -Wextra -pedantic-errors -pedantic -Werror
and I don't get any errors during compilation (or warnings) (should I get any?)
Question
Is safe to use LWPOLY (actually pointed by LWGEOM*) in functions that accept LWGEOM and don't modify the void *data; member. I understand that this is poor man's inheritance but this is what I need to work with.
Details
POLYGON:
typedef struct
{
uint8_t type; /* POLYGONTYPE */
uint8_t flags;
GBOX *bbox;
int32_t srid;
int nrings; /* how many rings we are currently storing */
int maxrings; /* how many rings we have space for in **rings */
POINTARRAY **rings; /* list of rings (list of points) */
}
LWPOLY; /* "light-weight polygon" */
LWGEOM:
typedef struct
{
uint8_t type;
uint8_t flags;
GBOX *bbox;
int32_t srid;
void *data;
}
LWGEOM;
POINTARRAY:
typedef struct
{
/* Array of POINT 2D, 3D or 4D, possibly missaligned. */
uint8_t *serialized_pointlist;
/* Use FLAGS_* macros to handle */
uint8_t flags;
int npoints; /* how many points we are currently storing */
int maxpoints; /* how many points we have space for in serialized_pointlist */
}
POINTARRAY;
GBOX:
typedef struct
{
uint8_t flags;
double xmin;
double xmax;
double ymin;
double ymax;
double zmin;
double zmax;
double mmin;
double mmax;
} GBOX;
Am I violating strict aliasing rule when I do something like?
const LWGEOM* lwgeom;
...
const LWPOLY* lwpoly = reinterpret_cast<const LWPOLY*>(lwgeom);
I know that in PostGis types are specifically designed to be "compatible" however I'd like to know if I am violating the standard by doing so.
Also, I noticed that PostGis is not compiled with strict aliasing disabled by default (at least version 2.1.5).
Solution
My colleague helped me to investigate it and it seems the answer is No it doesn't violate strict aliasing, but only in case we access LWGEOMS members that are of the same type as of LWPOLY's and are laid out in the beginning of the struct contiguously. Here is why (quoting standard):
3.10.10 says that you can access a member through a pointer to "aggregate or union".
8.5.1 defines aggregates (C structs are aggregates):
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or
protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
9.2.19 says that pointer to the struct is the same as pointer to the fist member for standard layout classes (C structs are standard layout).
Whether this is a safe way to code is a different question.
Yes, it violates the strict aliasing rule. LWGEOM and LWPOLY are unrelated types, and so are int and void*. So, for example, modification to lwgeom->data may not be read through lwpoly->nrings and vice versa.
I validated this with GCC4.9. My code is as follows:
#include <cinttypes>
#include <iostream>
using namespace std;
typedef struct {
uint8_t type; /* POLYGONTYPE */
uint8_t flags;
int32_t srid;
int nrings; /* how many rings we are currently storing */
} LWPOLY; /* "light-weight polygon" */
typedef struct {
uint8_t type;
uint8_t flags;
int32_t srid;
void *data;
} LWGEOM;
void f(LWGEOM* pgeom, LWPOLY* ppoly) {
ppoly->nrings = 7;
pgeom->data = 0;
std::cout << ppoly->nrings << '\n';
}
int main() {
LWGEOM geom = {};
LWGEOM* pgeom = &geom;
LWPOLY* ppoly = (LWPOLY*)pgeom;
f(pgeom, ppoly);
}
Guess what, the output is 7.
I got error while I was tying to pass structure from RPC client to server. Client calls Output3 procedure.
Definition in IDL:
struct BarStruct
{
byte a;
int b;
byte c;
char* d;
char* ddd;
};
void Output3([in] handle_t hBinding, [in, out] struct BarStruct* b);
Generated in header:
struct BarStruct
{
byte a;
int b;
byte c;
char *d;
char *ddd;
} ;
void Output3(
/* [in] */ handle_t hBinding,
/* [out][in] */ struct BarStruct *b);
implementation in server side:
void Output3(handle_t hBinding, struct BarStruct * b)
{
std::cout << "a=" << b->a << std::endl;
}
Client side code:
BarStruct b;
b.a=10;
std::cout<<"Output3"<<std::endl ;
Output3(hBinding, &b);
What might be wrong?
Your structure contains pointer to something, in the specific case pointer to char. When you want to transfer this to another process you have to keep in mind that a pointer is just and address value. When you want to pass the data where the pointer points to you need something different like a conformant array.
The basic idea is that you have to pass the length of the array that is address by the pointer.