Strings
Introduction
The use of strings in PIC code requires careful consideration due to the need to avoid hardcoded memory addresses. Here are common approaches.
When you declare a string literal in your C code, the compiler includes that string directly into the executable binary (.data,
.rdata
) at compile time. This means that the memory addresses of these string literals are hard-coded into the executable, making them part of the binary image itself.
TL;DR Since the memory addresses of string literals are hard-coded, they can lead to issues with position independence in PIC code. To address this, techniques like string hashing or using string pointers are employed to avoid directly embedding string literals with hard-coded memory addresses in the executable.
Using Strings in PIC
When using strings in PIC code, prefer methods like string hashing or using string pointers to ensure position independence. Always avoid the use of string literals.
String Hashing
String Hashing: This is the best method. Involves calculating a hash value for the string at compile time and passing the hash value instead of the string itself. At runtime, the hash value can be used to look up the corresponding string from a predefined table or mapping structure. This approach avoids passing the actual string directly, ensuring position independence.
String Pointers
Instead of passing the string itself, you can pass a pointer to the string. This pointer can point to a string stored in memory dynamically allocated using functions like HeapAlloc or malloc. By passing the pointer, you avoid hardcoding the string in the function call, making the code position independent.
String Constants
If you have a limited set of strings that are known at compile time, you can define them as constants using #define or const char* and pass them directly to the function. However, this approach should be used with caution as it still involves hardcoding the string values in the code. It may not be suitable for cases where strings are dynamically generated or obtained from external sources.
String Macros
Using #define
to create string constants does not hardcode memory addresses directly into the compiled binary. When you use #define
to define a string constant like #define STRING "example"
, it simply replaces occurrences of STRING
with "example"
in your source code during the preprocessing stage.
Example:
The preprocessor replaces STRING
with "example"
before the code is compiled:
Note: This is just an example, "%s\n"
is still a string literal.
Last updated