When I want to access some value in C struct in assembly, I usually just add something to the struct's address. However, when this struct is large, it's quite a bit tiring... Is there any trick or normal option to declare global label inside?
How to access C struct value in assembly?
To get the addresses of individual members, like you rightly pointed out, you have to add a constant offset to the address of the struct. The problem essentially boils down to automatically calculating these offsets for a given struct and member.
Even for small structs, I would suggest not calculating the offsets by hand because compilers add different padding between members and hints like __attribute__(packed) are not available for all compilers.
For most of my projects I use a separate program to generate an offsets header at build time.
The basic idea is to create a .c/.cpp file with something like -
// Your program headers that define the structs here
#include <stdio.h>
#include <stddef.h>
#define OFFSET(x, str, mem) printf("#define " #x " %d\n",(int) offsetof(str, mem))
#define SIZE(x, str) printf("#define " #x " %d\n", (int) sizeof(str))
#define HEADER_START() printf("#ifndef ASM_OFFSET_H\n#define ASM_OFFSET_H\n")
#define HEADER_END() printf("#endif\n")
int main(int argc, char *argv[]) {
HEADER_START();
OFFSET(struct_name_member_name, struct_name, member_name); // Substitute your struct name and member name here
SIZE(struct_name_size, struct_name); // This macro is to get the size of a struct
HEADER_END();
return 0;
}
Executing this program during the build time generates a header file that can be included directly with GASM. For other assemblers you can change the syntax to generate appropriate inc files.
The benefit of this approach is that the program uses the same headers as your C/C++ code. That way when you change any headers, the generated offsets should change automatically.
One thing you have to be careful here is that this technique does not work well if you are cross compiling for a different architecture and the compiler uses a different layout on your host vs the target. If you want something similar for cross compilation, I can write a separate answer.
If the structure is not too complicated, try a web search for "masm h2inc". H2INC.EXE (also needs H2INC.ERR) is an old Microsoft utility that will convert a .h file for a C program into a .inc file for MASM. Although this is part of a 16 bit toolset, the programs are 32 bit programs that use a dos extender and will run on Win XP, Win 7 64 bit, but I haven't tested Win 10 64 bit.
It doesn't seem to support 64 bit integers or 64 bit pointers (since it was mean for 16 bit Microsoft C code). You could work with a modified .h file and then post fix the .inc file.
There are other versions of h2inc from third parties that can support more current features, some of which will show up in a search for "masm h2inc".
Related
I'm having this struct here (bool is an unsigned char)
typedef struct
{
bool a;
int b;
int c;
} test_t;
If I look at the memory of a variable using this type declared on stack I see that the aligned of member b is not correct and is not on 4 bytes boundary.
EDIT: This is caused by the inclusion of FreeRTOS_IP.h which includes a ported file for ti CCS pack_struct_start.h / pack_struct_end.h. The pack_struct_end.h file is not working correctly causing all remaining structs to stay packed.
Why the TI compiler packs my structure by default and then access the memory like they are not packed?
The compiler does what you tell it to do. In your case, you don't tell it very much, so the compiler does what others tell it to instead.
Specifically, your structure is probably in a header file that gets included in a random string of #includes in different files, but since you don't specify packing parameters (which by the way are #pragma pack, not the all-or-nothing gcc-specific attribute) it uses whatever leaked from the other header files you included.
Here's the lesson to learn from this: if you care at all, at any point, about the memory layout of your structure (ie, if you use it to lazily access memory from files or network data), always specify a packing attribute on your structure. No exceptions, ever. Also clean up after yourself (#pragma pack(pop)).
I have a program written originally WAY back in 1995, maintained to 2012.
It's obviously written for a 32-bit architecture, I've managed to get the damn thing running, but I'm getting stumped on how it's saving data...
My issue is with the sizeof(long) under 64-bit (a common problem I know), I've tried doing a sed across the code and replacing long with int_32t, but then I get errors where it's trying to define a variable like:
unsigned long int count;
I've also tried -m32 on the gcc options, but then it fails to link due to 64-bit libraries being required.
My main issue is where it tries to save player data (it's a MUD), at the following code lines:
if ((sizeof(char) != 1) || (int_size != long_size))
{
logit(LOG_DEBUG,
"sizeof(char) must be 1 and int_size must == long_size for player saves!\n");
return 0;
}
Commenting this out allows the file to save, but because it's reading bytes from a buffer as it reloads the characters, the saved file is no longer readable by the load function.
Can anyone offer advice, maybe using a typedef?
I'm trying to avoid having to completely rewrite the save/load routines - this is my very last resort!.
Thanks in advance for answers!
Instead of using types like int and long you can use int32_t and int64_t, which are typedef:s to types that have the correct size in your environment. They exists in signed and unsigned variants as in int32_t and uint32_t.
In order to use them you need to include stdint.h. If you include inttypes.h you will also get macros useful when printing using printf, e.g. PRIu64.
I would like to develop a device-driver on linux(written in C) and a user-space library wrapping all functions provided by my device-driver (also written in C). Just to make it more clear, my library wil provide the following methods:
int myOpen();
void myClose();
mySetConf(MyconfStruct conf)
etc.
The function will use the file associated to my device-driver, in particular:
myOpen will call the open() of my device-driver
myClose will call the close() of my device-driver
mySetConf will call the ioctl() of my device driver and pass the myConfStruct as a parameter to configure the device-driver using ioctl().
assume myConfStruct is a simple structure containing something like this:
typedef struct {
uint16_t var1;
uint8_t var2;
} myConfStruct;
I would like the myConfStruct to be a structure shared between both my user-application (library) and my kernel-driver using a single header.
Are there any best-practice while doing this?
I would like to have the structure defined into only one file, having it defined in multiple files seems to be quite error-prone if i plan on changing it in the future, but I understood that I should not include <linux/types.h> inside my user files and I shouldn't use <stdint.h> inside my device-driver.
So another question is also, how can I define the interface between a module and the user-application so that who is implementing the application is not forced to include any linux header?
What you are creating is a character device. The kernel documentation includes a specific section, the Linux driver implementer's guide, you should also read. Specifically, the ioctl based interfaces section, which also describes some of the considerations necessary (regarding alignment and 64-bit fields).
As to header files, see KernelHeaders article at kernelnewbies.org.
I would like to have the structure defined into only one file, having it defined in multiple files seems to be quite error-prone if i plan on changing it in the future.
No. You do specify the headers in two separate files: one for use in-kernel, and the other for use by userspace.
Kernel-userspace interface should be stable. You should take care to design your data structure so that you can extend it if necessary; preferably by adding some padding reserved for future use and required to be initialized to zero, and/or a version number at the beginning of the structure. Later versions must support all previous versions of the structure as well. Even if it is only a "toy" or "experimental" device driver, it is best to learn to do it right from the get go. This stuff is much, much harder to learn to "add afterwards"; I'm talking from deep experience here.
As a character device, you should also be prepared for the driver to be compiled on other architectures besides the one you are developing on. Even byte order ("endianness") can vary, although all Linux architectures are currently either ILP32 or LP64.
Also remember that there are several hardware architectures, including x86-64, that support both 64-bit and 32-bit userspace. So, even if you believe your driver will ever be used on x86-64, you cannot really assume the userspace is 64-bit (and not 32-bit). Look at existing code to see how it is done right; I recommend using e.g. bootlin's elixir to browse the Linux kernel sources.
Kernel-side header file should use __s8, __u8, __s16, __u16, __s32, __u32, __s64, or __u64. For pointers, use __u64, and u64_to_user_ptr().
Userspace-side header file should use <stdint.h> types (int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) and uint64_t for pointers. Use a cast via (uintptr_t) for the conversion, i.e. ptr = (void *)(uintptr_t)u64; and u64 = (uintptr_t)ptr.
Ensure all members are naturally aligned. This means that an N-bit member is preceded by k×N bits of other members, where k is either zero or a positive integer. Thus, if your structure needs an unsigned and a signed 8-bit integer (one for version, one for foo), an 16-bit signed integer (bar), and a 64-bit unsigned integer (baz), considering the version should be first, you'll probably want
struct kernel_side {
__u8 version;
__s8 foo;
__u16 bar;
__u32 padding;
__u64 baz;
};
struct userspace_side {
uint8_t version;
int8_t foo;
uint16_t bar;
uint32_t padding;
uint64_t baz;
};
You can also have character arrays and such, but do note that a single ioctl data block is limited to 8191 bytes or less in length.
If you spend some time designing your interface structures, you'll find that careful design will avoid annoying issues like compat_ support (making them just simple wrappers). Personally, I end up creating a test version with a userspace test program to see what works best, and only then decide on the data structures.
I have a header file. It contains the value of various constants(as pre-processor macro definitions---hash defines) that I use in my embedded systems project(IDE is Keil MicroVision, Microcontroller is STM32 and programming language is C).
I want to convert that header file to a hex file, so that I can separately write it to flash memory of the microcontroller.
Hence, for a single general software code, I wish to to change the constants and run it for specific (around 10-15 different types) hardware.
My approach: I am trying to find a way to convert the header file to a binary file first, and then use some utility(srecorder from sourceforge) to convert the .bin to .hex
Is this approach right?
Or can anyone please suggest an alternate and effective way to achieve my goal?
Thanks
Preprocessor defines aren't stored in data flash but in program flash (.text), together with the code using them, integrated in the machine code. They aren't stored at any specific or fixed address. So your request doesn't make any sense - you simply cannot program them to flash separately.
In order to achieve that you need const uint32_t or similar variables stored at fixed memory locations. These need to be declared in a .c file, though it is sometimes acceptable to expose read-only variables "globally" with extern references from a corresponding .h file.
To allocate a variable at a specific address you typically need to change the linker script and use non-standard compiler extensions.
Understanding where you're coming from, I would not recommend going down the road you suggested. Let me show you two ways to solve your problem which I believe are much better.
I'll assume your constants are macros, but, it should not be different if they are enums or something else.
First option is to use the preprocessor to select your platform. Something like:
#if defined(PLATFORM_A)
#define CONSTANT_X 111
#define CONSTANT_Y 222
#elif defined(PLATFORM_B)
#define CONSTANT_X 112
#define CONSTANT_Y 221
#else
#error Need to define a platform
#endif
Of course, if you have a lot of constants, maybe keeping each platform in its own header would be better (easier to read).
#if defined(PLATFORM_A)
#include "platform_a_constants.h"
#elif defined(PLATFORM_B)
#include "platform_b_constants.h"
#else
#error Need to define a platform
#endif
This option is the only way if you use these constants to, say, dimension an array.
I don't have experience with Keil IDE's, so, I'm not sure how to configure it to build different binaries with different macro definitions, but, it's a common C thing, there should be way to do it.
Another option would be to make these globals. In that case, you would have a single header like:
extern int const constant_x;
extern int const constant_y;
And then a separate source file for each platform:
// platform_a.c
int const constant_x = 111;
int const constant_y = 222;
// platform_b.c
int const constant_x = 112;
int const constant_y = 221;
Again, how to link in only the source file that you need for a particular target depends on your build system and I'm not familiar with Keil IDE, but it should not be hard to do.
In general, this option is a little easier to maintain, as it's just setting up the linker, you don't mess up with source code in any way (and defining a preprocessor constant is messing up with the source code in potentially ugly ways).
Also, with this option it's simple to turn a constant into a runtime parameter, which can be changed during the execution of the program, if need be - just drop the const from the declaration and definitions.
I'm pretty new to c programming and I have this following program to degub. Problem is, I have no idea what these lines of code even mean. Could anyone point me in the direction of what they mean as far as from a syntax point of view/functionality? What does the code do? The code is compiled with MPLab C30 v3.23 or higher.
fractional abcCoefficient[3] __attribute__ ((space(xmemory))); /*ABC Coefficients loaded from X memory*/
fractional controlHistory[3] __attribute__ ((space(ymemory))); /*Control History loaded from Y memory*/
fractional kCoeffs[] = {0,0,0}; /*Kp,Ki,and Kd gains array initialized to zero*/
These lines declare variables; there's no execution code associated with what you've pasted.
The environment this code is intended for understands that fractional is a type; either in the same file or in a header this file includes (directly or indirectly), fractional will be defined with a typedef statement. In your examples, each of the variables are arrays of three fractional types.
The __attribute__ ((space(?memory))) entries are attributes the compiler intended to build this understands and affect something regarding how the variables are managed. You'll want to consult the compiler documentation for the platform you're using.
See this page to learn about __attribute__ in gcc (however, I don't see a space(xmemory) option in there, consult your compiler's documentation if it's not gcc. If it is, then space() can be a macro).
fractional is also a custom type, search for typedef definitions for fractional.
Basically, the code is creating a bunch of arrays of type fractional. The first two make use of gcc's attribute extension (or whatever compiler you are using), and the last one is initialized to 0 on every position.
The first two lines declare arrays with three elements each. The type is fractional, which is probably a typedef (to a struct with numerator and denominator?).
The comments suggest that the data is stored in another memory space, perhaps some sort of Flash.
So the program seems to be for an embedded system.
It looks like "fractional" is a custom type, look for its typedef somewhere and it should get you started on what you're looking at. I expect these are variable declarations.
Macros are established using the "#define" preprocessor directive, so you can look for "#define space(x) code" somewhere to tell you what it does. Good luck.