Why would I need this?
The location of a datum keeps changing because input data varies too much, so other than printing it, sleeping for 30 seconds so I can manually enter it into GDB, then continuing the program, it might be useful to just let the program tell GDB where to watch.
But is such a thing possible?
You can get close; assuming for simplicity C/C++ language
Define a function that returns a reference to your datum to track:
// debug.h
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
You can then subsequently just
(gdb) display GetDatumForDebug()
or even
(gdb) display GetDatumForDebug()->s
I assume it will be possible to use the result of GetDatumForDebug() in your debug watches, I'm not sure what you do/how you do that :)
Here is a working example, crammed in a single source (test.cpp) for speed: compile with g++ -g test.cpp -o test:
static bool s_initialized = false;
struct mydatastruct { const char* s; };
static mydatastruct& some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
{
static mydatastruct s_instance = { "hello world" };
s_initialized = true;
return s_instance;
}
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
int main()
{
// force initialize for demo purpose:
some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return 42;
}
Automate gdb commands
Append the following to .gdbinit in your working directory:
break main
run
call some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
display GetDatumForDebug()? GetDatumForDebug()->s : ""
This will automatically execute these commands on launching gdb in that directory
Related
I'm trying to implement an error handler using the clock() function from the "time.h" library. The code runs inside an embeeded system (Colibri IMX7 - M4 Processor). The function is used to monitor a current value within a specific range, if the value of the current isn't correct the function should return an error message.
The function will see if the error is ocurring and in the first run it will save the first appearance of the error in a clock_t as reference, and then in the next runs if the error is still there, it will compare the current time using clock() with the previous reference and see if it will be longer than a specific time.
The problem is that the function clock() is always returning -1. What should I do to avoid that? Also, why can't I declare a clock_t variable as static (e.g. static clock_t start_t = clock()?
Please see below the function:
bool CrossLink_check_error_LED_UV_current_clock(int current_state, int current_at_LED_UV)
{
bool has_LED_UV_current_deviated = false;
static int current_number_of_errors_Current_LED_CANNON = 0;
clock_t startTimeError = clock();
const int maximum_operational_current_when_on = 2000;
const int minimum_turned_on_LED_UV_current = 45;
if( (current_at_LED_UV > maximum_operational_current_when_on)
||(current_state!=STATE_EMITTING && (current_at_LED_UV > minimum_turned_on_LED_UV_current))
||(current_state==STATE_EMITTING && (current_at_LED_UV < minimum_turned_on_LED_UV_current)) ){
current_number_of_errors_Current_LED_CANNON++;
if(current_number_of_errors_Current_LED_CANNON > 1) {
if (clock() - startTimeError > 50000){ // 50ms
has_LED_UV_current_deviated = true;
PRINTF("current_at_LED_UV: %d", current_at_LED_UV);
if(current_state==STATE_EMITTING){
PRINTF(" at state emitting");
}
PRINTF("\n\r");
}
}else{
if(startTimeError == -1){
startTimeError = clock();
}
}
}else{
startTimeError = 0;
current_number_of_errors_Current_LED_CANNON = 0;
}
return has_LED_UV_current_deviated;
}
Edit: I forgot to mention before, but we are using GCC 9.3.1 arm-none-eabi compiler with CMake to build the executable file. We have an embedeed system (Colibri IMX7 made by Toradex) that consists in 2 A7 Processors that runs our Linux (more visual interface) and the program that is used to control our device runs in a M4 Processor without an OS, just pure bare-metal.
For a lot of provided functions in the c standard library, if you have the documentation installed (usually it gets installed with the compiler), you can view documentation using the man command in the shell. With man clock, it tells me that:
NAME
clock - determine processor time
SYNOPSIS
#include <time.h>
clock_t clock(void);
DESCRIPTION
The clock() function returns an approximation of processor time used by the program.
RETURN VALUE
The value returned is the CPU time used so far as a clock_t; to get the number of seconds used, divide by
CLOCKS_PER_SEC. If the processor time used is not available or its value cannot be represented, the function
returns the value (clock_t) -1.
etc.
This tells us that -1 means that the processor time (CLOCK_PROCESS_CPUTIME_ID) is unavailable. The solution is to use CLOCK_MONOTONIC instead. We can select the clock we want to use with clock_gettime.
timespec clock_time;
if (clock_gettime(CLOCK_MONOTONIC, &clock_time)) {
printf("CLOCK_MONOTONIC is unavailable!\n");
exit(1);
}
printf("Seconds: %d Nanoseconds: %ld\n", clock_time.tv_sec, clock_time.tv_nsec);
To answer the second part of your question:
static clock_t start_time = clock();
is not allowed because the return value of the function clock() is not known until runtime, but in C the initializer of a static variable must be a compile-time constant.
You can write:
static clock_t start_time = 0;
if (start_time == 0)
{
start_time = clock();
}
But this may or may not be suitable to use in this case, depending on whether zero is a legitimate return value of the function. If it could be, you would need something like:
static bool start_time_initialized = false;
static clock_t start_time;
if (!start_time_initialized)
{
start_time_initialized = true;
start_time = clock();
}
The above is reliable only if you cannot have two copies of this function running at once (it is not re-entrant).
If you have a POSIX library available you could use a pthread_once_t to do the same as the above bool but in a re-entrant way. See man pthread_once for details.
Note that C++ allows more complicated options in this area, but you have asked about C.
Note also that abbreviating "start time" as start_t is a very bad idea, because the suffix _t means "type" and should only be used for type names.
in the end the problem was that since we are running our code on bare metal, the clock() function wasn't working. We ended up using an internal timer on the M4 Processor that we found, so now everything is fine. Thanks for the answers.
We use a third party Tcl parsing library to validation Tcl script for both syntax and semantic checking. The driver was written in C and defined a set of utility functions. Then it calls Tcl_CreateObjCommand so the script could call these C functions. Now we are in the process of porting the main program to go and I could not find a way to do this. Anyone know a way to call golang functions from Tcl script?
static int
create_utility_tcl_cmds(Tcl_Interp* interp)
{
if (Tcl_CreateObjCommand(interp, "ip_v4_address",
ip_address, (ClientData)AF_INET, NULL) == NULL) {
TCL_CHECKER_TCL_CMD_EVENT(0, "ip_v4_address");
return -1;
}
.....
return 0;
}
Assuming you've set the relevant functions as exported and built the Go parts of your project as in
Using Go code in an existing C project
[…]
The important things to note are:
The package needs to be called main
You need to have a main function, although it can be empty.
You need to import the package C
You need special //export comments to mark the functions you want callable from C.
I can compile it as a C callable static library with the following command:
go build -buildmode=c-archive foo.go
Then the core of what remains to be done is to write the C glue function from Tcl's API to your Go code. That will involve a function something like:
static int ip_address_glue(
ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
// Need an explicit cast; ClientData is really void*
GoInt address_family = (GoInt) clientData;
// Check for the right number of arguments
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "address");
return TCL_ERROR;
}
// Convert the argument to a Go string
GoString address;
int len;
address.p = Tcl_GetStringFromObj(objv[1], &len);
address.n = len; // This bit is hiding a type mismatch
// Do the call; I assume your Go function is called ip_address
ip_address(address_family, address);
// Assume the Go code doesn't fail, so no need to map the failure back to Tcl
return TCL_OK;
}
(Credit to https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf for providing enough information for me to work out some of the type bindings.)
That's then the function that you register with Tcl as the callback.
Tcl_CreateObjCommand(interp, "ip_v4_address", ip_address_glue, (ClientData)AF_INET, NULL);
Theoretically, a command registration can fail. Practically, that only happens when the Tcl interpreter (or a few critical namespaces within it) is being deleted.
Mapping a failure into Tcl is going to be easiest if it is encoded at the Go level as an enumeration. Probably easiest to represent success as zero. With that, you'd then do:
GoInt failure_code = ip_address(address_family, address);
switch (failure_code) {
case 0: // Success
return TCL_OK;
case 1: // First type of failure
Tcl_SetResult(interp, "failure of type #1", TCL_STATIC);
return TCL_ERROR;
// ... etc for each expected case ...
default: // Should be unreachable, yes?
Tcl_SetObjResult(interp, Tcl_ObjPrintf("unexpected failure: %d", failure_code));
return TCL_ERROR;
}
Passing back more complex return types with tuples of values (especially a combination of a success indicator and a “real” result value) should also be possible, but I've not got a Go development environment in order to probe how they're mapped at the C level.
I'd like to attach gdb to a process where I can't easily control the startup of the process because it is run from inetd and where the process completes too fast to be able to attach to it once it starts.
What I'd like to do is insert a bit of code at the particular point that I want to start debugging. That code would ideally wait for the debugger to attach and then continue. I've tried with a sleep but it is then tricky to choose a delay long enough that I have time to catch it but short enough not to be a nuisance waiting for it to elapse after gdb is attached.
Is there any better choices of code to insert or to call for this purpose?
What I'd like to do is insert a bit of code at the particular point that I want to start debugging.
I usually do it like this:
volatile int done = 0;
while (!done) sleep(1);
Attach GDB (you'll be inside sleep). Do finish, then set var done = 1, and enjoy the rest of your debugging session ;-)
using namespace std;
using namespace std::this_thread;
using namespace chrono;
void waitForDebugger()
{
steady_clock::time_point tp1, tp2, tp3;
microseconds d1 = microseconds(10000);
microseconds d2 = microseconds(20000);
bool looped = false;
while (true)
{
sleep_for(d1);
tp1 = steady_clock::now();
if (looped && duration_cast<microseconds>(tp1 - tp3) > d2)
{
break;
}
sleep_for(d1);
tp2 = steady_clock::now();
if (looped && duration_cast<microseconds>(tp2 - tp1) > d2)
{
break;
}
sleep_for(d1);
tp3 = steady_clock::now();
if (looped && duration_cast<microseconds>(tp3 - tp2) > d2)
{
break;
}
looped = true;
}
}
I'm playing around with the D programming language and am wondering how I
can grab a character without requiring the user to press enter.
Pseudocode example of what I want:
while(true){
if(userHasPressedChar()){
writeln(getChar());
}
}
In C++ I can use conio.h's "getch()", but i have yet to find anything similar here.
Edit: I am using Windows 7.
Edit 2: I found a solution at this forum, which I could alter for my own use.
module main;
import std.stdio;
import core.sys.windows.windows;
void main() {
auto hCon = GetStdHandle(STD_INPUT_HANDLE);
FlushConsoleInputBuffer(hCon);
for(;;) { // in default console mode, ctrl-C will terminate
INPUT_RECORD inrec;
DWORD numread;
while(inrec.EventType != KEY_EVENT) {
WaitForSingleObject(hCon, INFINITE);
ReadConsoleInputW(hCon, &inrec, 1, &numread);
}
auto keyEvent = inrec.KeyEvent;
writefln("VK: %x \tChar: %x \tState: %x",
keyEvent.wVirtualKeyCode,
keyEvent.UnicodeChar,
keyEvent.dwControlKeyState);
}
}
You can also use various libraries. For example, my terminal.d can do this https://github.com/adamdruppe/arsd/blob/master/terminal.d for windows and linux.
Here's an example file from my book (see my SO profile if you're interested) that demonstrates the usage http://arsdnet.net/dcode/book/chapter_12/07/input.d
import terminal;
void main() {
auto terminal = Terminal(ConsoleOutputType.linear);
auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw);
terminal.writeln("Press any key to exit");
auto ch = input.getch();
terminal.writeln("Bye!");
}
The input object does the necessary conversions to the console mode to turn off line buffering and cleans up after itself. Once you create one, you have methods like input.getch() and input.kbhit() similarly to conio.
My terminal library also offers other event types for things like mouse input if you want to get into more advanced usages.
To compile, just download terminal.d and add it to your command, e.g. dmd yourfile.d terminal.d.
I am installing a new newbuf driver on FreeBSD 10.0 . After compiling with make the driver.ko file has been created and than kldload can load successfully. kldload returns 0 and I can see the device at the kldstat output. When attempt to use the driver opening the /dev/** file, the file is not exist.
I think that this /dev/** file should be created by make_dev function which is located in device_attach member method. To test if the kldload reaches this attaching function; when write printf and uprintf to debug the driver, I can not see any output at console nor dmesg output.
But the problem is after writing printf at beginnings (after local variable definitions) of device_identify and device_probe functions, I can't see any output again at console nor dmesg.
My question is that even if the physical driver has problem (not located etc.), should I see the ouput of printf at the device_identify member function which is called by kldload at starting course (I think)?
Do I have a mistake when debugging newbuf driver with printf (I also tried a hello_world device driver and at this driver I can take output of printf at dmesg)?
Mainly how can I test/debug this driver's kldload processes?
Below some parts of my driver code (I think at least I should see MSG1, but I can not see):
struct mydrv_softc
{
device_t dev;
};
static devclass_t mydrv_devclass;
static struct cdevsw mydrv_cdevsw = {
.d_version = D_VERSION,
.d_name = "mydrv",
.d_flags = D_NEEDGIANT,
.d_open = mydrv_open,
.d_close = mydrv_close,
.d_ioctl = mydrv_ioctl,
.d_write = mydrv_write,
.d_read = mydrv_read
};
static void mydrv_identify (driver_t *driver, device_t parent) {
devclass_t dc;
device_t child;
printf("MSG1: The process inside the identfy function.");
dc = devclass_find("mydrv");
if (devclass_get_device(dc, 0) == NULL) {
child = BUS_ADD_CHILD(parent, 0, "mydrv", -1);
}
}
static int mydrv_probe(device_t dev) {
printf("MSG2: The process inside the probe function.");
mydrv_init();
if (device_get_unit(dev) != 0)
return (ENXIO);
device_set_desc(dev, "FreeBSD Device Driver");
return (0);
}
static int mydrv_attach(device_t dev) {
struct mydrv_softc *sc;
device_printf(dev, "MSG3: The process will make attachment.");
sc = (struct mydrv_softc *) device_get_softc(dev);
sc->dev = (device_t)make_dev(&mydrv_cdevsw, 0, UID_ROOT, GID_WHEEL, 0644, "mydrv_drv");
return 0;
}
static int mydrv_detach(device_t dev) {
struct mydrv_softc *sc;
sc = (struct mydrv_softc *) device_get_softc(dev);
destroy_dev((struct cdev*)(sc->dev));
bus_generic_detach(dev);
return 0;
}
static device_method_t mydrv_methods[] = {
DEVMETHOD(device_identify, mydrv_identify),
DEVMETHOD(device_probe, mydrv_probe),
DEVMETHOD(device_attach, mydrv_attach),
DEVMETHOD(device_detach, mydrv_detach),
{ 0, 0 }
};
static driver_t mydrv_driver = {
"mydrv",
mydrv_methods,
sizeof(struct mydrv_softc),
};
DRIVER_MODULE(mydrv, ppbus, mydrv_driver, mydrv_devclass, 0, 0);
If you don't see your printf's output on your console then your device functions will probably not be called. Can you show us your module's code?
Have you used DRIVER_MODULE() or DEV_MODULE()?
What parent bus are you using?
I guess printf works fine, but I prefer to use device_printf as it also prints the device name, and will be easier when looking through logs or dmesg output. Also leave multiple debug prints and check the log files on your system. Most logs for the device drivers are logged in /var/log/messages. But check other log files too.
Are you running your code on a virtual machine? Some device drivers don't show up their device files in /dev if the OS is running on a virtual machine. You should probably run your OS on actual hardware for the device file to show up.
As far as I know, you can't see the output in dmesg if you cannot find the corresponding device file in /dev but you may have luck with logs as I mentioned.
The easiest way to debug is of course using the printf statements. Other than this, you can debug the kernel using gdb running on another system. I am not familiar with the exact process but I know you can do this. Google it.