Thread overview
Translation of C struct to D
Nov 14, 2011
Michael Kremser
Nov 15, 2011
Jerry
Nov 15, 2011
Michael Kremser
Nov 15, 2011
Bernard Helyer
Nov 15, 2011
Iain Buclaw
Nov 16, 2011
Michael Kremser
Nov 16, 2011
Trass3r
Nov 17, 2011
Michael Kremser
November 14, 2011
Hi!

I currently try to create a simple linux driver (for test purposes) just like in [1] in D based on [2]. The main difficulty is to call register_chrdev. It expects an argument "fops" of type file_operations which can look like that in C:

static struct file_operations fops = {
	.read = device_read,
	.write = device_write,
	.open = device_open,
	.release = device_release
};

device_read and so on are functions. Originally, file_operations has much more fields and it's possible to omit unused fields.

What I tried so far: I declared "register_chrdev" as follows:

extern (C):
int register_chrdev (uint major, char *name, file_operations *fops);

My try for the translation of file_operations looks like that:

struct file_operations {
	int function() open;
	int function() release;
};

In init_module() I have the following code:

char[] DEVICE_NAME = "dtestdev";
file_operations fops;
fops.open = &device_open;
fops.release = &device_close;
Major = register_chrdev(0, std.string.toStringz(DEVICE_NAME), &fops);

The code compiles with some warnings, and if I try to insert it into the kernel, I get some messages in the kernel log.

WARNING: "_D3std6string9toStringzFAaZPa" [...../hello.ko] undefined!
WARNING: "_Dmodule_ref" [...../hello.ko] undefined!
WARNING: "_D15TypeInfo_Struct6__vtblZ" [...../hello.ko] undefined!
WARNING: "register_chrdev" [...../hello.ko] undefined!
WARNING: "_D3std6string12__ModuleInfoZ" [...../hello.ko] undefined!

Nov 14 21:12:39 eeepc1104 kernel: [17127.068990] hello: Unknown symbol _D3std6string12__ModuleInfoZ (err 0)
Nov 14 21:12:39 eeepc1104 kernel: [17127.069613] hello: Unknown symbol register_chrdev (err 0)
Nov 14 21:12:39 eeepc1104 kernel: [17127.070462] hello: Unknown symbol _D15TypeInfo_Struct6__vtblZ (err 0)
Nov 14 21:12:39 eeepc1104 kernel: [17127.071359] hello: Unknown symbol _Dmodule_ref (err 0)
Nov 14 21:12:39 eeepc1104 kernel: [17127.072352] hello: Unknown symbol _D3std6string9toStringzFAaZPa (err 0)

Any help greatly appreciated.

Greetings

Michael

[1] http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN680
[2] http://iainbuclaw.wordpress.com/2010/05/22/writing-a-linux-kernel-module-in-d/
November 15, 2011
Michael Kremser <mkspamx-usenet@yahoo.de> writes:

> Hi!
>
> I currently try to create a simple linux driver (for test purposes) just like in [1] in D based on [2]. The main difficulty is to call register_chrdev. It expects an argument "fops" of type file_operations which can look like that in C:
>
> static struct file_operations fops = {
> 	.read = device_read,
> 	.write = device_write,
> 	.open = device_open,
> 	.release = device_release
> };
>
> device_read and so on are functions. Originally, file_operations has much more fields and it's possible to omit unused fields.
>
> What I tried so far: I declared "register_chrdev" as follows:
>
> extern (C):
> int register_chrdev (uint major, char *name, file_operations *fops);
>
> My try for the translation of file_operations looks like that:
>
> struct file_operations {
> 	int function() open;
> 	int function() release;
> };
>
> In init_module() I have the following code:
>
> char[] DEVICE_NAME = "dtestdev";
> file_operations fops;
> fops.open = &device_open;
> fops.release = &device_close;
> Major = register_chrdev(0, std.string.toStringz(DEVICE_NAME), &fops);
>
> The code compiles with some warnings, and if I try to insert it into the kernel, I get some messages in the kernel log.
>
> WARNING: "_D3std6string9toStringzFAaZPa" [...../hello.ko] undefined!
> WARNING: "_Dmodule_ref" [...../hello.ko] undefined!
> WARNING: "_D15TypeInfo_Struct6__vtblZ" [...../hello.ko] undefined!
> WARNING: "register_chrdev" [...../hello.ko] undefined!
> WARNING: "_D3std6string12__ModuleInfoZ" [...../hello.ko] undefined!
>
> Nov 14 21:12:39 eeepc1104 kernel: [17127.068990] hello: Unknown symbol
> _D3std6string12__ModuleInfoZ (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.069613] hello: Unknown symbol
> register_chrdev (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.070462] hello: Unknown symbol
> _D15TypeInfo_Struct6__vtblZ (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.071359] hello: Unknown symbol
> _Dmodule_ref (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.072352] hello: Unknown symbol
> _D3std6string9toStringzFAaZPa (err 0)
>
> Any help greatly appreciated.

This looks like you don't have druntime or phobos linked into your module code.

Does the original C example work for you?
November 15, 2011
Jerry thought it would be a good idea to write me on 15.11.2011 05:01 GMT +0100 (CET):
> 
> This looks like you don't have druntime or phobos linked into your
> module code.  

My Makefile looks as follows:

# D compiler
DC := gdc
# D objects
DOBJS := dinterface.o

ifneq ($(MAKE_KBUILD),)
# kbuild part of makefile

obj-$(CONFIG_HELLO) := hello.o
hello-y += $(DOBJS)

else
# normal part of makefile

KERNELDIR := /lib/modules/$(shell uname -r)/build

all: $(DOBJS)
	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) CONFIG_HELLO=m MAKE_KBUILD=1 modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) MAKE_KBUILD=1 clean

%.o: %.d
	$(DC) -c $< -o $@

endif

Is there something missing?

> Does the original C example work for you? 

Yes, it works, and also the "Hello World" module in D from the other webpage works.
November 15, 2011
kbuild is almost certainly not linking in phobos.

November 15, 2011
On 14 November 2011 20:54, Michael Kremser <mkspamx-usenet@yahoo.de> wrote:
> Hi!
>
> I currently try to create a simple linux driver (for test purposes) just like in [1] in D based on [2]. The main difficulty is to call register_chrdev. It expects an argument "fops" of type file_operations which can look like that in C:
>
> static struct file_operations fops = {
>        .read = device_read,
>        .write = device_write,
>        .open = device_open,
>        .release = device_release
> };
>
> device_read and so on are functions. Originally, file_operations has much more fields and it's possible to omit unused fields.
>
> What I tried so far: I declared "register_chrdev" as follows:
>
> extern (C):
> int register_chrdev (uint major, char *name, file_operations *fops);
>
> My try for the translation of file_operations looks like that:
>
> struct file_operations {
>        int function() open;
>        int function() release;
> };
>
> In init_module() I have the following code:
>
> char[] DEVICE_NAME = "dtestdev";
> file_operations fops;
> fops.open = &device_open;
> fops.release = &device_close;
> Major = register_chrdev(0, std.string.toStringz(DEVICE_NAME), &fops);
>
> The code compiles with some warnings, and if I try to insert it into the kernel, I get some messages in the kernel log.
>
> WARNING: "_D3std6string9toStringzFAaZPa" [...../hello.ko] undefined!
> WARNING: "_Dmodule_ref" [...../hello.ko] undefined!
> WARNING: "_D15TypeInfo_Struct6__vtblZ" [...../hello.ko] undefined!
> WARNING: "register_chrdev" [...../hello.ko] undefined!
> WARNING: "_D3std6string12__ModuleInfoZ" [...../hello.ko] undefined!
>
> Nov 14 21:12:39 eeepc1104 kernel: [17127.068990] hello: Unknown symbol
> _D3std6string12__ModuleInfoZ (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.069613] hello: Unknown symbol
> register_chrdev (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.070462] hello: Unknown symbol
> _D15TypeInfo_Struct6__vtblZ (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.071359] hello: Unknown symbol
> _Dmodule_ref (err 0)
> Nov 14 21:12:39 eeepc1104 kernel: [17127.072352] hello: Unknown symbol
> _D3std6string9toStringzFAaZPa (err 0)
>
> Any help greatly appreciated.
>
> Greetings
>
> Michael
>
> [1] http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN680
> [2]
> http://iainbuclaw.wordpress.com/2010/05/22/writing-a-linux-kernel-module-in-d/
>

If you are going to write a kernel module, do not use or rely any part of the D, or C standard library. Do not attempt to do anything that would generate hidden calls to the D runtime library, or would depend on there being one.  Otherwise you will find yourself hitting a total system freeze when loading the module into the kernel. :~)


Rather than using toStringz, you should be able to get by with declaring the register_chrdev function as follows.

extern(C)
int register_chrdev (uint major, in char *name, file_operations *fops)



Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
November 16, 2011
Am 2011-11-16 00:53, schrieb Iain Buclaw:

> Rather than using toStringz, you should be able to get by with
> declaring the register_chrdev function as follows.
>
> extern(C)
> int register_chrdev (uint major, in char *name, file_operations *fops)

This yields the following compiler error:

Error: cannot implicitly convert expression (DEVICE_NAME) of type char[] to char*

If I try to cast with register_chrdev(0, (char*)DEVICE_NAME, &fops); the following error appears:

C style cast illegal, use cast(char*)DEVICE_NAME

Best regards

Michael
November 16, 2011
> If I try to cast with register_chrdev(0, (char*)DEVICE_NAME, &fops); the following error appears:
>
> C style cast illegal, use cast(char*)DEVICE_NAME

Or use DEVICE_NAME.ptr
November 17, 2011
Am 2011-11-16 23:23, schrieb Trass3r:
>> If I try to cast with register_chrdev(0, (char*)DEVICE_NAME, &fops);
>> the following error appears:
>>
>> C style cast illegal, use cast(char*)DEVICE_NAME
>
> Or use DEVICE_NAME.ptr

Compilation now succeeded, but when I try to load with insmod, the following errors appear:

Nov 17 15:03:49 eeepc1104 kernel: [43799.326876] hello: Unknown symbol _D3std6string12__ModuleInfoZ (err 0)
Nov 17 15:03:49 eeepc1104 kernel: [43799.327297] hello: Unknown symbol register_chrdev (err 0)
Nov 17 15:03:49 eeepc1104 kernel: [43799.327702] hello: Unknown symbol _D15TypeInfo_Struct6__vtblZ (err 0)
Nov 17 15:03:49 eeepc1104 kernel: [43799.328252] hello: Unknown symbol

Best regards

Michael