Initializing struct member with type DWORD64 - c

I use Microsoft Visual Studio 2010, write in C++ and compile binary for x64 platform. In my project I have useful structure for memory blocks with data pointer and size:
typedef struct _MEMORY_BLOCK
{
DWORD64 Length;
LPBYTE lpData;
}
MEMORY_BLOCK, *LPMEMORY_BLOCK;
In other file I have key definition:
BYTE PublicKey[] = { 0x01, 0x02, 0x03, ... };
DWORD64 PublicKeyLength = (DWORD64)sizeof(PublicKey);
MEMORY_BLOCK ServerKey = { PublicKeyLength, PublicKey };
On x86 platform structure initialization of ServerKey works fine, but on x64 platform it results in MEMORY_BLOCK struct filled with zeroes. If I change members order in structure (e.g. lpData at first, and second is Length), lpData initializes properly, but Length is still equal to zero.
Now I have workaround with function that sets ServerKey values in runtime, but I need to know why I could not initialize DWORD64 struct member in ServerKey definition.

Related

How to initialize an array of structs to a value other than zero like 0xFF?

I have an array of structs that I need to initialize at compile-time (no memset) to 0xFF. This array will be written as part of the program over erased flash. By setting it to 0xFF, it will remain erased after programming, and the app can use it as persistent storage. I've found two ways to do it, one ugly and one a workaround. I'm wondering if there's another way with syntax I haven't found yet. The ugly way is to use a nested initializer setting every field of the struct. However, it's error prone and a little ugly. My workaround is to allocate the struct as an array of bytes and then use a struct-typed pointer to access the data. Linear arrays of bytes are much easier to initialize to a non-zero value.
To aid anyone else doing the same thing, I'm including the gcc attributes used and the linker script portion.
Example struct:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512] __attribute__(( packed ));
} __attribute__(( packed ));
Initialize to 0xFF using the best way I know:
// Allocate the space as an array of bytes
// because it's a simpler syntax to
// initialize to 0xFF.
__attribute__(( section(".bootloader_data") ))
uint8_t bootloaderDataArray[sizeof(struct BlData_t)] = {
[0 ... sizeof(struct BlData_t) - 1] = 0xFF
};
// Use a correctly typed pointer set to the
// array of bytes for actual usage
struct BlData_t *bootloaderData = (struct BlData_t *)&bootloaderDataArray;
No initialization necessary because of (NOLOAD):
__attribute__(( section(".bootloader_data") ))
volatile const struct BLData_t bootloader_data;
Addition to linker script:
.bootloader_data (NOLOAD):
{
FILL(0xFF); /* Doesn't matter because (NOLOAD) */
. = ALIGN(512); /* start on a 512B page boundary */
__bootloader_data_start = .;
KEEP (*(.bootloader_data)) /* .bootloader_data sections */
KEEP (*(.bootloader_data*)) /* .bootloader_data* sections */
. = ALIGN(512); /* end on a 512B boundary to support
runtime erasure, if possible */
__bootloader_data_end = .;
__bootloader_data_size = ABSOLUTE(. - __bootloader_data_start);
} >FLASH
How to use the starting address, ending address and size in code:
extern uint32_t __bootloader_data_start;
extern uint32_t __bootloader_data_end;
extern uint32_t __bootloader_data_size;
uint32_t _bootloader_data_start = (uint32_t)&__bootloader_data_start;
uint32_t _bootloader_data_end = (uint32_t)&__bootloader_data_end;
uint32_t _bootloader_data_size = (uint32_t)&__bootloader_data_size;
Update:
It turns out that I was asking the wrong question. I didn't know about the (NOLOAD) linker section attribute which tells the program loader not to burn this section into flash. I accepted this answer to help others realize my mistake and possibly theirs. By not even programming the section, I don't have to worry about the initialization at all.
I've upvoted the union answers since they seem to be a good solution to the question I asked.
I would use a union of your struct together with an array of the correct size, then initialize the array member.
union {
struct BlData_t data;
uint8_t bytes[sizeof(struct BlData_t)];
} data_with_ff = {
.bytes = {
[0 ... sizeof(struct BlData_t) - 1] = 0xff
}
};
You can then access your struct as data_with_ff.data, defining a pointer or macro for convenience if you wish.
Try on godbolt
(Readers should note that the ... in a designated initializer is a GCC extension; since the question was already using this feature and is tagged gcc I assume that is fine here. If using a compiler that doesn't have it, I don't know another option besides .bytes = { 0xff, 0xff, 0xff ... } with the actual correct number of 0xffs; you'd probably want to generate it with a script.)
The sensible way to do this is to find the command in the linker script telling it to back off from touching that memory in the first place. Because why would you want it do be erased only to filled up with 0xFF again? That only causes unnecessary flash wear for nothing.
Something along the lines of this:
.bootloader_data (NOLOAD) :
{
. = ALIGN(512);
*(.bootloader_data *)
} >FLASH
If you truly need to do this initialization and in pure standard C, then you can wrap your inner struct inside an anonymous union (C11), then initialize that one using macro tricks:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
union {
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512];
uint8_t raw [512];
};
};
#define INIT_VAL 0xFF, // note the comma
#define INIT_1 INIT_VAL
#define INIT_2 INIT_1 INIT_1
#define INIT_5 INIT_2 INIT_2 INIT_1
#define INIT_10 INIT_5 INIT_5
/* ... you get the idea */
#define INIT_512 INIT_500 INIT_10 INIT_2
const struct BlData_t bld = { .raw = {INIT_512} };
This method could also be applied on whole struct basis, if you for example want to initialize a struct array with all items set to the same values at compile-time.

What is this unknown NTFS field?

The Microsoft documentation for NTFS describes the structure of an attribute. It shows it as follows:
typedef struct _ATTRIBUTE_RECORD_HEADER {
ATTRIBUTE_TYPE_CODE TypeCode;
ULONG RecordLength;
UCHAR FormCode;
UCHAR NameLength;
USHORT NameOffset;
USHORT Flags;
USHORT Instance;
union {
struct {
ULONG ValueLength;
USHORT ValueOffset;
UCHAR Reserved[2];
} Resident;
struct {
VCN LowestVcn;
VCN HighestVcn;
USHORT MappingPairsOffset;
UCHAR Reserved[6];
LONGLONG AllocatedLength;
LONGLONG FileSize;
LONGLONG ValidDataLength;
LONGLONG TotalAllocated;
} Nonresident;
} Form;
} ATTRIBUTE_RECORD_HEADER, *PATTRIBUTE_RECORD_HEADER;
The final member of a nonresident attribute, TotalAllocated, does not seem to exist. 3rd party documentation does not mention it, and actual NTFS filesystem do not contain such a member (the ValidDataLength is immediately followed by the the data runs, as specified in MappingPairsOffset.
From the documentation itself, it is supposed to record the total number of clusters (as opposed to the total number of bytes).
TotalAllocated
The total allocated for the file (the sum of the allocated clusters).
Does anyone recognize this?
The field actually does exist, but only on compressed files (i.e. bit 1 on the Flags field is set); The MappingPairsOffset is then 0x48 instead of the usual 0x40 to make room for the extra field.
This is mentioned in a footnote to 3rd party NTFS documentation here.

rte_mbuf in dpdk 18.08 doesnt have struct rte_pktmbuf pkt

I am getting the below compilation error after upgrading to dpdk 18.08 version.
error: ‘struct rte_mbuf’ has no member named ‘pkt’
m->pkt.data = ((char*)m->pkt.data - (BTG_IP_VHL_HL(ip->version_ihl) << 2));
^
As per the documentation rte_mbuf struct no longer has packet message buffer struct rte_pktmbuf pkt which inturn holds void* data which contains start address of data in segment buffer.
struct rte_mbuf {
.
.
.
union {
struct rte_ctrlmbuf ctrl;
struct rte_pktmbuf pkt;
};
}
struct rte_pktmbuf {
/* valid for any segment */
struct rte_mbuf *next;
void* data; /**< Start address of data in segment buffer. */
Please let me know which other field of rte_mbuf struct can be used with dpdk 18.08 version which means start address of data in the packet message buffer so as to resolve this compilation error.Thanks in advance.
It's rte_pktmbuf_mtod(m, t) macro.
A macro that points to the start of the data in the mbuf.
The returned pointer is cast to type t. Before using this function, the user must ensure that the first segment is large enough to accommodate its data.
Source: DPDK API
Update:
To prepend a packet buffer with some data, there is a dedicated function for that: rte_pktmbuf_prepend() (and here is DPDK documentation)
It's hard to be 100% sure without the context of your old code, but it looks like this fragment must be rewritten to:
rte_pktmbuf_prepend(m,
BTG_IP_VHL_HL(ip->version_ihl) << 2);

Initializing, constructing and converting struct to byte array causes misalignment

I am trying to design a data structure (I have made it much shorter to save space here but I think you get the idea) to be used for byte level communication:
/* PACKET.H */
#define CM_HEADER_SIZE 3
#define CM_DATA_SIZE 16
#define CM_FOOTER_SIZE 3
#define CM_PACKET_SIZE (CM_HEADER_SIZE + CM_DATA_SIZE + CM_FOOTER_SIZE)
// + some other definitions
typedef struct cm_header{
uint8_t PacketStart; //Start Indicator 0x5B [
uint8_t DeviceId; //ID Of the device which is sending
uint8_t PacketType;
} CM_Header;
typedef struct cm_footer {
uint16_t DataCrc; //CRC of the 'Data' part of CM_Packet
uint8_t PacketEnd; //should be 0X5D or ]
} CM_Footer;
//Here I am trying to conver a few u8[4] tp u32 (4*u32 = 16 byte, hence data size)
typedef struct cm_data {
union {
struct{
uint8_t Value_0_0:2;
uint8_t Value_0_1:2;
uint8_t Value_0_2:2;
uint8_t Value_0_3:2;
};
uint32_t Value_0;
};
//same thing for Value_1, 2 and 3
} CM_Data;
typedef struct cm_packet {
CM_Header Header;
CM_Data Data;
CM_Footer Footer;
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
typedef struct cm_appendresult{
uint8_t Result;
uint8_t Reason;
} CM_AppendResult;
extern CM_InitTypeDef cmHandler;
The goal here is to make reliable structure for transmitting data over USB interface. At the end the CM_Packet should be converted to an uint8_t array and be given to data transmit register of an mcu (stm32).
In the main.c file I try to init the structure as well as some other stuff related to this packet:
/* MAIN.C */
uint8_t packet[CM_PACKET_SIZE];
int main(void) {
//use the extern defined in packet.h to init the struct
cmHandler.DeviceId = 0x01; //assign device id
CM_Init(&cmHandler); //construct the handler
//rest of stuff
while(1) {
CM_GetPacket(&cmHandler, (uint8_t*)packet);
CDC_Transmit_FS(&packet, CM_PACKET_SIZE);
}
}
And here is the implementation of packet.h which screws up everything so bad. I added the packet[CM_PACKET_SIZE] to watch but it is like it is just being generated randomly. Sometimes by pure luck I can see in this array some of the values that I am interested in! but it is like 1% of the time!
/* PACKET.C */
CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *cm_initer) {
cmHandler.DeviceId = cm_initer->DeviceId;
static CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier,
uint8_t *data){
CM_AppendResult result;
switch(identifier){
case CM_VALUE_0:
handler->Packet.Data.Value_0_0 = data[0];
handler->Packet.Data.Value_0_1 = data[1];
handler->Packet.Data.Value_0_2 = data[2];
handler->Packet.Data.Value_0_3 = data[3];
break;
//Also cases for CM_VALUE_0, 1 , 2
//to build up the CM_Data sturct of CM_Packet
default:
result.Result = CM_APPEND_FAILURE;
result.Reason = CM_APPEND_CASE_ERROR;
return result;
break;
}
result.Result = CM_APPEND_SUCCESS;
result.Reason = 0x00;
return result;
}
void CM_GetPacket(CM_InitTypeDef *handler, uint8_t *packet){
//copy the whole struct in the given buffer and later send it to USB host
memcpy(packet, &handler->Packet, sizeof(CM_PACKET_SIZE));
}
So, the problem is this code gives me 99% of the time random stuff. It never has the CM_START which is the start indicator of packet to the value I want to. But most of the time it has the CM_END byte correctly! I got really confused and cant find out the reason. Being working on an embedded platform which is hard to debugg I am kind of lost here...
If you transfer data to another (different) architecture, do not just pass a structure as a blob. That is the way to hell: endianess, alignment, padding bytes, etc. all can (and likely will) cause trouble.
Better serialize the struct in a conforming way, possily using some interpreted control stream so you do not have to write every field out manually. (But still use standard functions to generate that stream).
Some areas of potential or likely trouble:
CM_Footer: The second field might very well start at a 32 or 64 bit boundary, so the preceeding field will be followed by padding. Also, the end of that struct is very likely to be padded by at least 1 bytes on a 32 bit architecture to allow for proper alignment if used in an array (the compiler does not care you if you actually need this). It might even be 8 byte aligned.
CM_Header: Here you likely (not guaranteed) get one uint8_t with 4*2 bits with the ordering not standardized. The field my be followed by 3 unused bytes which are required for the uint32_t interprettion of the union.
How do you guarantee the same endianess (for >uint8_t: high byte first or low byte first?) for host and target?
In general, the structs/unions need not have the same layout for host and target. Even if the same compiler is used, their ABIs may differ, etc. Even if it is the same CPU, there might be other system constraints. Also, for some CPUs, different ABIs (application binary interface) exist.

C how to base structs off of struct

I'm trying to write some code dealing with a register interface. The register interface is generic and used all over the chip I'm working with. There are several different types of instantiations which use a subset of the register interface.
I want to know, is there some way in C to create a struct with the master register interface, then have the various subsets be structs that only can access their used registers?
So, for example, let's call the different possible subsets A, B, and C.
The register interface may look something like this:
OFFSET NAME NEEDED BY
0x00 -- CFG A B C
0x04 -- VERSION A B C
0x08 -- SIZE B C
0x0C -- TYPE A C
0x10 -- USER A
So, using the same format that ARM uses for their SCS register interface, I can create the following struct for master:
typedef volatile struct {
uint32 cfg;
uint32 version;
uint32 size;
uint32 type;
uint32 user;
} master_t;
That part's relatively straightforward. But I'm having trouble thinking of a way to implement the a_t, b_t, and c_t types to have their contents still point to the right offsets, short of just creating separate structs in the exact same method as above (which would make it extremely painful to propagate changes/bugfixes; the actual use case has more like 50 total registers for master_t).
Essentially, my end goal is that if you pointed an a_t to the right memory address, then tried to write code that would (e.g.) try to access a_t.size, the compiler would throw an error. Is there any way this is possible in C?
Perhaps like this:
typedef struct
{
uint32 cfg;
uint32 version;
uint32 filler;
uint32 type;
uint32 user;
} SUB_A_T;
typedef struct
{
uint32 cfg;
uint32 version;
uint32 size;
} SUB_B_T;
typedef struct
{
uint32 cfg;
uint32 version;
uint32 size;
uint32 type;
} SUB_C_T;
typedef UNION
{
SUB_A_T a;
SUB_B_T b;
SUB_C_T c;
} MASTER_T;
To access:
MASTER_T master;
master.a.cfg = 1;
master.a.version = 2;
master.a.type = 3;
master.a.user = 4;
// master.a.size = 11 This line would cause a compiler error.
Or...
master.b.cfg = 10;
master.b.version = 20;
master.b.size = 30;
// master.b.type = 22 This line would cause a compiler error.
// master.b.user = 33 This line would cause a compiler error.
Or...
master.c.cfg = 100;
master.c.version = 200;
master.c.size = 300;
master.c.type = 400;
// master.c.user = 44 This line would cause a compiler error.

Resources