packed structs in tcc - c

I am trying to do packed struct in tcc C compiller.
Code is as follows and __attribute __ tag should be supported:
#include <stdio.h>
#include <stdint.h>
typedef struct _test_t{
char c;
uint16_t i;
char d;
} __attribute__((__packed__)) test_t;
int main(){
test_t x;
x.c = 0xCC;
x.i = 0xAABB;
x.d = 0xDD;
const char *s = (const char *) & x;
unsigned i;
for(i = 0; i < sizeof(x); i++)
printf("%3u %x\n", i, 0xFF & s[i]);
return 0;
}
It works in gcc, but not work on tcc.
I also tried __attribute __((packed)) and few other tests - none works.

As you already found the __attribute__ extension applies only to struct's members, so each of them should have it applied individually. Here is your code with minor adaptations, that compiles with tcc 0.9.26 and then runs with correct output:
typedef struct {
char c __attribute__((packed));
unsigned short i __attribute__((packed));
char d __attribute__((packed));
} test_t;
int main(void)
{
test_t x;
printf("%zu\n", sizeof(test_t));
x.c = 0xCC;
x.i = 0xAABB;
x.d = 0xDD;
const char *s = (const char *) &x;
unsigned i;
for (i = 0; i < sizeof(x); i++)
printf("%3u %x\n", i, 0xFF & s[i]);
return 0;
}
Result:
4
0 cc
1 bb
2 aa
3 dd
There is one catch here. As you may already spotted there are no headers. The correctly written code should have:
#include <stdio.h>
#include <stdint.h> // then replace unsigned short with uint16_t
However, with headers the __attribute__ is no longer working. I am not sure if that always happen, but on my system (CentOS 6) it does exactly in that way.
As I found the explanation lies in internal sys/cdefs.h header, that contains:
/* GCC has various useful declarations that can be made with the
`__attribute__' syntax. All of the ways we use this do fine if
they are omitted for compilers that don't understand it. */
#if !defined __GNUC__ || __GNUC__ < 2
# define __attribute__(xyz) /* Ignore */
#endif
so the __attribute__ function-like macro is "washed-up" for tcc, as it does not define __GNUC__ macro. It seems to be some incoherence between tcc developers and standard library (here glibc) writers.

I can confirm that at least with tcc 0.9.26 attribute((packed)) on
struct members is not working. Using Windows-style packing pragmas works just fine:
#if defined(__TINYC__)
#pragma pack(1)
#endif
typedef struct {
uint16_t ..
} interrupt_gate_descriptor_t;
#if defined(__TINYC__)
#pragma pack(1)
#endif

Seems to be error with TCC.
according many sources , including this one, http://wiki.osdev.org/TCC
this should work:
struct some_struct {
unsigned char a __attribute__((packed));
unsigned char b __attribute__((packed));
} __attribute__((packed));
... but it does not work.

Related

Can a bit field structure be instantiated as an immediate?

Suppose I have the following (made up) definition:
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
I know I can use this to initialize a variable that gets passed to a function, such as :
color_t white = {.red = 0x7, .grn = 0x7, .blu = 0x3};
printf("color is %x\n", white.reg);
... but in standard C, is it possible to instantiate a color_t as an immediate for passing as an argument without assigning it first to a variable?
[I discovered that yes, it's possible, so I'm answering my own question. But I cannot promise that this is portable C.]
Yes, it's possible. And the syntax more or less what you'd expect. Here's a complete example:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
int main() {
// initializing a variable
color_t white = {.bits={.red=0x7, .grn=0x7, .blu=0x3}};
printf("color1 is %x\n", white.reg);
// passing as an immediate argument
printf("color2 is %x\n", (color_t){.bits={.red=0x7, .grn=0x7, .blu=0x3}}.reg);
return 0;
}

Arrays in c shared library

I want to basically process a struct array in a method in a dynamic library, but when I pass the array and print it (in the exact same manner as in my main program) it has different values.
Consider a struct like this:
struct color {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
}
And the code to print it looks like this:
printf("pos: %p\n", array);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) array)[i]);
}
Now, what I'm doing in the test program is this:
printf("Table:\n");
print(table, size);
and the output looks like this (as excepted):
pos: 0x7fff5b359530
bgra: 00000000
bgra: ff0000ff
bgra: ff00ffff
But when i execute the same code in a function in the library this is what i get:
pos: 0x7fff5b359530
bgra: 00000008
bgra: 00000030
bgra: 5b3598e0
Now I'm wondering what I'm doing wrong, since i can't see a fault in my code. Also, the values must correlate somehow since, the output is always the same (Except for the address of course).
header.h
#include <stdint.h>
#ifndef __HEADER_H_
#define __HEADER_H_
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
void print(struct bmpt_color_bgra *table, uint8_t size);
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size);
#endif
library.c
#include <stdlib.h>
#include <stdio.h>
#include "header.h"
#define EXPORT __attribute__((visibility("default")))
__attribute__((constructor))
static void initializer(void) {
printf("[%s] initializer()\n", __FILE__);
}
__attribute__((destructor))
static void finalizer(void) {
printf("[%s] finalizer()\n", __FILE__);
}
EXPORT
void print(struct bmpt_color_bgra *table, uint8_t size) {
uint8_t i;
printf("pos: %p\n", table);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) table)[i]);
}
}
EXPORT
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size) {
printf("table in func:\n");
print(table, size);
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char **argv) {
struct bmpt_color_bgra arr[3];
struct bmpt_color_bgra c;
c.b = 0x0;
c.g = 0x0;
c.r = 0x0;
c.a = 0x0;
arr[0] = c;
c.b = 0xff;
c.a = 0xff;
arr[1] = c;
c.r = 0xff;
arr[2] = c;
//the first result (the correct one)
print(arr, 3);
//the second result
gen(arr, 3);
}
This probably comes down to memory alignment of the members within the struct, and the size of the struct itself differing between your program and the dynamic/shared library. You don't mention which compiler you are using, but using different compiler(s) or compiler options for your program and the shared library could cause this effect.
You can preserve binary compatibility between modules by specifying exactly how the members of the struct should be aligned. E.g in GCC you can force how the struct is represented in memory by use of an attribute.
See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html for GCC alignment instructions
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} __attribute__ ((packed));
Also take a look at Byte Alignment for integer (or other) types in a uint8_t array for a similar question.

Finding offset of a structure element in c

struct a
{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
Can anybody explain me how to find the offset of int k so that we can find the address of int i?
Use offsetof() to find the offset from the start of z or from the start of x.
offsetof() - offset of a structure member
SYNOPSIS
#include <stddef.h>
size_t offsetof(type, member);
offsetof() returns the offset of the field member from the
start of the structure type.
EXAMPLE
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}
You will get the following output on a Linux, if you compile with GCC:
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
It's been 3 years since the question has been asked, I'm adding my answer for the sake of completeness.
The hacky way of getting the offset of a struct member goes like this
printf("%p\n", (void*)(&((struct s *)NULL)->i));
It doesn't look pretty, I can't think of anything in pure C (which can get you the offset of the member, without knowing anything else about the structure. I believe the offsetof macro is defined in this fashion.
For reference, this technique is used in the linux kernel, check out the container_of macro :
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
A more elaborate explanation can be found in this article:
http://radek.io/2012/11/10/magical-container_of-macro/
struct a foo;
printf("offset of k is %d\n", (char *)&foo.y.k - (char *)&foo);
printf("offset of i is %d\n", (char *)&foo.x.i - (char *)&foo);
foo.x.i refers to the field i in the struct x in the struct foo.
&foo.x.i gives you the address of the field foo.x.i.
Similarly, &foo.y.k gives you the address of foo.y.k;
&foo gives you the address of the struct foo.
Subtracting the address of foo from the address of foo.x.i gives you the offset from foo to foo.x.i.
As Gangadhar says, you can use the offsetof() macro rather than the pointer arithmetic I gave. But it's good to understand the pointer arithmetic first.
As already suggested, you should use the offsetof() macro from <stddef.h>, which yields the offset as a size_t value.
For example:
#include <stddef.h>
#include <stdio.h>
#include "struct_a.h" /* Header defining the structure in the question */
int main(void)
{
size_t off_k_y = offsetof(struct c, k);
size_t off_k_z = offsetof(struct a, y.k);
size_t off_i_x = offsetof(struct b, i);
size_t off_i_z = offsetof(struct a, x.i);
printf("k = %zu %zu; i = %zu %zu\n", off_k_y, off_k_z, off_i_x, off_i_z);
return 0;
}
Example output:
k = 0 8; i = 0 0
To find the offset, this is one way we can go about it.
struct a{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
int main(){
struct a* foo = &z;
printf("%d\n", foo); //address of z
printf("%d\n", &(foo->y)); //address of z.y
printf("%d\n", &( (&(foo->y))->k )); //address of z.y.k
int offset_k = (char*)&( (&(foo->y))->k ) - (char*)foo ;
printf("%d\n", offset_k);
return 0;
}
Output would be similar to this:
4225552 //address of z
4225560 //address of z.y
4225560 //address of z.y.k
8 //offset
In this particular case, since int i is the first member of the struct, the base address of the struct will be that of int i as well. Otherwise, you could compute the offset of int i in a similar manner.
int offset_i = (char*)&( (&(foo->x))->i ) - (char*)foo; //0 in this case
NOTE: The offset will be negative or positive depending on how you define it (if it's with respect to base address or member z.y.k). Here, it is defined to be with respect to base address of struct.
Here's a generic solution that works with both newer and older versions of GNU C:
<!-- language: C -->
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(minMajor, minMinor) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((minMajor) << 16) + (minMinor))
#else
# define GNUC_PREREQ 0
#endif
#if GNUC_PREREQ(4, 0)
# define OFFSETOF(type, member) ((int)__builtin_offsetof(type, member))
#else
# define OFFSETOF(type, member) ((int)(intptr_t)&(((type *)(void*)0)->member) )
#endif
UPDATE: Someone asked for a usage example:
struct foo {
int bar;
char *baz;
}
printf("Offset of baz in struct foo = %d\n",
OFFSETOF(foo, baz));
Would print 4, if int compiles into 4 bytes on the architecture of the machine it runs on.

How to break struct members into bytes of a single word

Say I have a C structure like:
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData; } tempStruct;
Is there a way to put all of those 3 members of the struct into a single 32-bit word, yet still be able to access them individually?
Something with the help of unions?
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData;
}
tempStruct;
typedef union {
tempStruct myStruct;
UINT32 myWord;
} stuff;
Or even better (with no "intermediate" struct):
#include <stdlib.h>
#include <stdio.h>
typedef union {
struct {
int nRow:8;
int nCol:8;
int nData:16;
};
int myWord;
} stuff;
int main(int args, char** argv){
stuff a;
a.myWord=0;
a.nCol=2;
printf("%d\n", a.myWord);
return 0;
}
What about just referring to it as a UINT32? It's not like C is type-safe.
tempStruct t;
t.nRow = 0x01;
t.nCol = 0x02;
t.nData = 0x04;
//put a reference to the struct as a pointer to a UINT32
UINT32* word = (UINT32 *) &t;
printf("%x", *word);
You can then get the value of the struct as a 32-bit word by dereferencing the pointer. The specifics of your system may matter, though...if I run this on my machine, the value of word is 0x00040201---that is, the fields are in reverse order. I don't think that's necessarily going to be the case if you're trying to serialize this to another system, so it's not portable.
If you want to actually store it as a 32-bit integer and then refer to the fields individually, why not
UINT32 word = 0x01020004;
and then somewhere else...
UINT8* row(UINT32 word) {
return (UINT8 *) &word + 3;
}
UINT8* col(UINT32 word) {
return ((UINT8 *) &word) + 2;
}
UINT16* data(UINT32 word) {
return ((UINT16 *) &word);
}
Macros will facilitate portable endianness.
Yes, you can use bit fields in C to do that. Something like:
typedef struct {
unsigned nRow : 8;
unsigned nCol : 8;
unsigned nData : 16;
} tempStruct;
If you want to control the memory layout also, you might want to take a look at #pragma pack. A non-portable option available on some compilers for this.
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
nRow will take only 8 bit and nCol will take 8 bit and nDate will take 16bit.
This will work for you.
I just wrote sample program to see the size of it
#include<stdio.h>
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
typedef struct {
int nRow;
int nCol;
int nData; } tempStructZ;
int main(void) {
printf("%d\n", sizeof(tempStruct));
printf("%d\n", sizeof(tempStructZ));
return 0;
}
Output:
4
16

C struct padding

I can use pragma pack on various compilers to force structs to have fields which are not on their natural alignments.
Is this recursive - so suppose struct typedef A contains a field of typedef struct B. If use a pragma to pack A will this force struct B to be packed?
You have to hope not! Lets say you have a function that takes a parameter struct A:
void fn( struct A x ) ;
and then a packed struct B that has struct A as a member:
#pragma pack(1)
struct B
{
struct A a ;
}
If you pass the member a of B to fn(), the function has no knowledge of the packing in this instance, and would fail.
Other answerer's results notwithstanding, I performed the following test on VC++ 2010:
struct A
{
int a;
char b;
int c ;
} ;
struct B
{
struct A d ;
} ;
#pragma pack(1)
struct C
{
struct A d ;
} ;
#pragma pack(1)
struct D
{
int a;
char b;
int c ;
} ;
#pragma pack(1)
struct E
{
struct D ;
} ;
int main()
{
int a = sizeof(struct A) ;
int b = sizeof(struct B) ;
int c = sizeof(struct C) ;
int d = sizeof(struct D) ;
int e = sizeof(struct E) ;
}
Inspection of a, b, c, d and e in main() in the debugger yield:
a = 12
b = 12
c = 12
d = 9
e = 9
The packing of struct C has no effect on the size of its struct A member.
Just don't. The exact behavior of an ugly nonstandard extension is not something you can even ask questions about without specifying an exact platform/compiler you're working with. If you find yourself needing packed structs, you'd be better to figure out why your code is broken and fix it. Packed structs are a band-aid for broken code that do nothing to fix the root cause of the brokenness.
Folowing Nathon's post, I tried about the same thing on my computer:
#include <stdio.h>
#if defined PACK_FIRST || defined PACK_BOTH
#pragma pack(1)
#endif
struct inner {
char a;
double b;
};
#if defined PACK_SECOND || defined PACK_BOTH
#pragma pack(1)
#endif
struct outer {
char a;
struct inner b;
char c;
double d;
};
int main(void) {
printf("sizeof (char): %d (1, of course)\n", (int)sizeof (char));
printf("sizeof (double): %d\n", (int)sizeof (double));
printf("sizeof (inner): %d\n", (int)sizeof (struct inner));
printf("sizeof (outer): %d\n", (int)sizeof (struct outer));
return 0;
}
$ gcc 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 40
$ gcc -DPACK_FIRST 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19
$ gcc -DPACK_SECOND 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 26
$ gcc -DPACK_BOTH 4128061.c
$ ./a.out
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19
Apparently my gcc packs from the point where the #pragma line appears.
For the version of GCC I have handy, it looks like yes:
#include <stdio.h>
typedef struct
{
char a;
int b;
}inner_t;
#pragma pack(1)
typedef struct
{
char a;
inner_t inner;
} outer_t;
int main()
{
outer_t outer;
outer.inner.a = 'a';
outer.inner.b = 0xABCDEF01;
printf ("outer.inner.a: %c\n", outer.inner.a);
return 0;
}
And gdb breaking on the printf gives me...
(gdb) x/5xw &outer
0x7fffffffe4b0: 0xffff61a0 0xcdef01ff 0x000000ab 0x00000000
0x7fffffffe4c0: 0x00000000
inner.b is not word aligned. So under GCC 4.4.5 on a little endian 64-bit machine, nested structures are packed if the outer structure is packed. Pardon my typedefs, those of you who don't like them.

Resources