How to set a global variable value in C to shell environment variable? - u-boot

While porting U-Boot on a specific hardware,
a function has to parse a header to get OS entry point to jump into it.
Say, the function get's the os entry point into a global 'C' variable uint32_t osentry.
How to set this value to U-Boot shell command 'go'?
I see U-Boot go (shell) command, has to be set as go $entry
In few examples, I see the entry is fixed address set as shell environment value.
Whereas, for me it is in a global 'C' variable.

How to set a global variable value in C to shell environment variable?
Use the env_set_addr() function to set an environment variable for use as an address from an ordinary program variable.
From include/common.h:
/**
* env_set_addr - Set an environment variable to an address in hex
*
* #varname: Environment variable to set
* #addr: Value to set it to
* #return 0 if ok, 1 on error
*/
ADDENDUM
For some reason, I could n't find this function in the code base I use.
You neglect to mention what version of U-Boot that you are using.
env_set() and its friends were apparently introduced in version 2017.09 to replace setenv() and its friends.
I used similar setenv(), after formatting with sprintf.
Since version 2011.12 the simple setenv() has been augmented with setenv_addr() and/or setenv_hex(), which will convert the unsigned long integer to a string of hex digits for you.
If you are still using a version of U-Boot older than 2011.12, then you will have to do what you describe.

Related

Which C header defines the common variable names (PATH, HOME, IFS...)?

Chapter 8 of POSIX standard define a list of commonly used environment variables "that are frequently exported by widely used command interpreters and applications".
However I cannot find any C header providing their names in any of my unix-like systems.
I'm looking for something like:
#define ENV_PATH "PATH"
#define ENV_USER "USER"
#define ENV_IFS "IFS"
...
Where I can find such header? Any OS-specific header would work: I just don't want to invent names for the constants myself.
edit
If you are used to only mainstream operating systems, you might ask: why you want to use constants here? $PATH is always $PATH everywhere!
This is not actually true.
In Plan 9 from Bell Labs, environment variables are usually lowercase (apparently due to aesthetics).
In Jehanne, a new operating system derived by Plan 9, I'm reconsidering this design choice, to ease the integration of POSIX tools. However, since I like the lowercase environment variables, I'd like to be able to easily switch back to lowercase names when Jehanne will be "the one true operating system" :-D
As stated in the comments, there is no header file that provides any POSIX-specified list of environment variables used by applications and utilities.
A list of "certain variables that are frequently exported by widely used command interpreters and applications" can be found at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08. (The actual environment variable list requires reformatting but here it is anyway...)
It is unwise to conflict with certain variables that are frequently
exported by widely used command interpreters and applications:
ARFLAGS IFS MAILPATH PS1
CC LANG MAILRC PS2
CDPATH LC_ALL MAKEFLAGS PS3
CFLAGS LC_COLLATE MAKESHELL PS4
CHARSET LC_CTYPE MANPATH PWD
COLUMNS LC_MESSAGES MBOX RANDOM
DATEMSK LC_MONETARY MORE SECONDS
DEAD LC_NUMERIC MSGVERB SHELL
EDITOR LC_TIME NLSPATH TERM
ENV LDFLAGS NPROC TERMCAP
EXINIT LEX OLDPWD TERMINFO
FC LFLAGS OPTARG TMPDIR
FCEDIT LINENO OPTERR TZ
FFLAGS LINES OPTIND USER
GET LISTER PAGER VISUAL
GFLAGS LOGNAME PATH YACC
HISTFILE LPDEST PPID YFLAGS
HISTORY MAIL PRINTER
HISTSIZE MAILCHECK PROCLANG
HOME MAILER PROJECTDIR
To access the value of an environment variable, use the getenv() function.
The exec() function documentation specifies the char **environ variable:
In addition, the following variable, which must be declared by the
user if it is to be used directly:
extern char **environ;
is initialized as a pointer to an array of character pointers to the
environment strings. The argv and environ arrays are each terminated
by a null pointer. . The null pointer terminating the argv array is not counted in argc.
Applications can change the entire environment in a single operation
by assigning the environ variable to point to an array of character
pointers to the new environment strings. After assigning a new value
to environ, applications should not rely on the new environment
strings remaining part of the environment, as a call to getenv(),
putenv(), setenv(), unsetenv(), or
any function that is dependent on an environment variable may, on
noticing that environ has changed, copy the environment strings to a
new array and assign environ to point to it.
Any application that directly modifies the pointers to which the
environ variable points has undefined behavior.
Conforming multi-threaded applications shall not use the environ
variable to access or modify any environment variable while any other
thread is concurrently modifying any environment variable. A call to
any function dependent on any environment variable shall be considered
a use of the environ variable to access that environment variable.
You can do something like that and in get_env_variables function you modify what you want. Just create something like a strncmp function for check if you want to modify this variable or not.
int main(int ac, char **av, char **env){
int i = 0;
while (env[i] != NULL){
env[i] = get_env_variables(env[i]);
i++;
}
}
char *get_env_variables(char *str) {
// PUT SOME CODE HERE
}
EDIT : don't forgot to return new env[i].

How to share functions symbols and addresses between projects in C?

I have two distinct projects which are running on the same target.
I want my second project to use few functions written in the first project at specific addresses.
To do that I thought I could use the symbol table from the first project in the second but it doesn't work. (I use arm-none-eabi toolchain and -nm on .elf file to generate symbols table).
I know that is possible but how can I do that ?
Well, the brute-force approach will very likely work:
int (*far_function)(int a, int b, int c) = (int(*)(int, int, int)) 0xfeedf00d;
far_function(1, 2, 3);
In other words, just make a function pointer and initialize it using the known address.
If the address isn't well-known (which it won't be if the other application is re-built and you haven't taken steps to "lock" the target function to a particular address), I would instead add meta-data at some fixed address, that contains the pointer. The other application would embed this data, thereby "exporting" the location of the interesting function.
The addresses yielded by nm are the location of the symbols, but on Cortex-M which used the Thumb2 instruction set, those addresses cannot be used directly for jump/call/branch execution - it is necessary to set the LSB of the address to 1 to indicate Thumb mode.
For example:
typedef void (*voidFn_void_t)(void) ;
uint32_t symbol_address = symbolLookup( "myfunction" ) ;
symbol_address |= 1 ; // Make Thumb mode address
((voidFn_void_t)symbol_address)() ; // Make call
The called function must even then have no dependencies on the execution environment since it is executing in the environment of the caller, not that of the project it was built in. You may get away with it if the execution environment is be identical but maintaining that may be a problem.

Reading variables while debugging with GDB (C)

I am beginner with GDB debbuging. I need read variables in GDB, I use the command info variable and get this information:
0x000007c4 variable1.0
0x000007c8 variable2.1
I set a breakpoint inside the variables function and these are defined how type long *. How can I read the value inside these correctly? I tried with show, display, print $variable1, p/x variable and so on commands.
Sorry for my grammar, i am not native speaker.
To view the contents of memory use gdb's x/FMT ADDRESS command e.g. x/d 0x000007c4 (to display an integer sized object from address 0x000007c4 and format it in decimal).
The info variables command in gdb will list all global and static variables and their program addresses. You don't describe the language or implementation you're using, but in C the variable name "variable1.0" is not valid. Therefore it must have been created by some link editor or the compiler in a post-process. Therefore the symbol may not exist in debug information and is only accessible by directly viewing the contents of memory, which is why the gdb p command doesn't work (there is no valid expression to show you that variable because it's not a variable, but just a symbol at an address).

LLDB print a variable named class

I have a C programm in which a variable called class is used.
I'm trying to debug it with LLDB but I'm encountering the following problem:
(lldb) print class
error: warning: declaration does not declare anything
error: declaration of anonymous class must be a definition
error: 1 errors parsing expression
I believe this problem occurs because class is a reserved keyword in C++ and LLDB interprets the code passed to print as C++. Is there still a way to print the content of my variable?
(Please do not advise me to rename the variable, I would have come up with this myself, if it was possible)
The problem is that the lldb expression parser uses C++ references to implement the job of finding & extracting results from the expressions we run. So we currently have to compile the expressions as C++ expressions, and as you guessed, you can't use "class" in a C++ expression. At some point, we have to teach clang how to do "C with references" and then we'll be able to compile & execute real C expressions.
However, provided you have debug information for "class", you can print the value of the variable using the "frame variable" command, i.e.:
(lldb) frame variable class
The "frame variable" command does not use the expression parser, it goes directly to the debug information, extracts the type & location of the variable, and prints that directly. So it doesn't suffer this restriction. If "class" is a global variable, not a frame local, use target variable instead.
frame variable does support a limited set of "expression-like" features, you can say:
(lldb) frame variable class.member
or
(lldb) frame variable *class
but you can't use it to call functions or pass the variable to a function call.
If you need to do that you can run the command:
(lldb) frame variable -L class
which will print the location of the variable. Usually that's some address, in which case you can use
(TypeOfClass *) <Address From Frame Variable>
in your expression in place of "class". If the location turns out to be a register, then use "$" appropriately cast in your expression. If you are going to use the variable in a number of expressions, remember you can do:
(lldb) expr TypeOfClass *$class = (TypeOfClass *) <Address From Frame Variable>
and then just use $class in your subsequent expressions. If you got super-motivated, you could even write a Python command that automates these steps...

Reading static variable from a binary

I am trying to read the value of a static variable in C like:
int variable = value;
The thing is that I only have the binary, and the code with a fake value (it is for a lecture, where we study security aspects of software development).
I have been trying to read the value using the GDB, and
(gdb)info variables
which just gives me a list of the variables (including the one I'm looking for) and what seems to be an address, so I would like to know if there is a way to read the value using GDB?
In GDB, use the 'print' command:
print variable
Voila!

Resources