Set paramaters of Cooja Simulation - contiki

I'm trying to do some simulation of the RPL protocol using Contiki 3.0 and the Cooja Simulator. I'm using the sky motes and i'd like to see how the DODAG is formed and monitor the parameters of the network using the Collect View. I have some questions:
1) Where and how i can change the Objective function?
2) My sensors have 1mW energy consumption, i think that for real application is too much, since sensors needs to work for several years
3) Where i can change the other parameters of the simulation? Like Tx/Rx packets?
4) How I interpret the routing metric given in the collect view?
5) I noticed that when I change the position of a node the network is too much slow detecting the movement, RPL is not very fast, but in Cooja it takes too much time, is it possible? Do you have any suggestion for simulating moving sensors?

1) Your can set change objective function from contiki/core/net/rpl/rpl-conf.h
edit as per your requirement:
/*
* The objective function (OF) used by a RPL root is configurable through
* the RPL_CONF_OF_OCP parameter. This is defined as the objective code
* point (OCP) of the OF, RPL_OCP_OF0 or RPL_OCP_MRHOF. This flag is of
* no relevance to non-root nodes, which run the OF advertised in the
* instance they join.
* Make sure the selected of is inRPL_SUPPORTED_OFS.
*/
#ifdef RPL_CONF_OF_OCP
#define RPL_OF_OCP RPL_CONF_OF_OCP
#else /* RPL_CONF_OF_OCP */
#define RPL_OF_OCP RPL_OCP_MRHOF
#endif /* RPL_CONF_OF_OCP */
/*
* The set of objective functions supported at runtime. Nodes are only
* able to join instances that advertise an OF in this set. To include
* both OF0 and MRHOF, use {&rpl_of0, &rpl_mrhof}.
*/
#ifdef RPL_CONF_SUPPORTED_OFS
#define RPL_SUPPORTED_OFS RPL_CONF_SUPPORTED_OFS
#else /* RPL_CONF_SUPPORTED_OFS */
#define RPL_SUPPORTED_OFS {&rpl_mrhof}
#endif /* RPL_CONF_SUPPORTED_OFS */
/*
* Enable/disable RPL Metric Containers (MC). The actual MC in use
* for a given DODAG is decided at runtime, when joining. Note that
* OF0 (RFC6552) operates without MC, and so does MRHOF (RFC6719) when
* used with ETX as a metric (the rank is the metric). We disable MC
* by default, but note it must be enabled to support joining a DODAG
* that requires MC (e.g., MRHOF with a metric other than ETX).
*/
#ifdef RPL_CONF_WITH_MC
#define RPL_WITH_MC RPL_CONF_WITH_MC
#else /* RPL_CONF_WITH_MC */
#define RPL_WITH_MC 0
#endif /* RPL_CONF_WITH_MC */
2) Contiki provides radio duty cycle (RDC) mechanisms for long term operation of nodes.
Default is nullrdc in which node always remains on hence life is less. Set ContikiMAC for minimizing power of nodes.
goto contiki/core/contiki-default-conf.h and edit as per your requirement.
e.g.
#ifndef NETSTACK_CONF_RDC
/* #define NETSTACK_CONF_RDC nullrdc_driver */
#define NETSTACK_CONF_RDC contikimac_driver
#endif /* NETSTACK_CONF_RDC */
3) Tx/Rx can be set from Network visualizer itself. You can right click any node and edit tx/rx range as well as success ratio.
You can also edit the same in .csc (simulation) file.
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>100.0</transmitting_range>
<interference_range>120.0</interference_range>
<success_ratio_tx>0.9</success_ratio_tx>
<success_ratio_rx>0.9</success_ratio_rx>
</radiomedium>
4) You have to calculate various performance metrics. For that you have code script file yourself (tough part).
Or use these links
https://github.com/iloveyii/contiki_rpl/tree/master/perl
https://pdfs.semanticscholar.org/d319/4d5f43f1cd3995ba7c9e99776ac8f150d445.pdf
5) Use mobility plugin to simulate various mobility models.
https://anrg.usc.edu/contiki/index.php/Mobility_of_Nodes_in_Cooja
http://vrajesh2188.blogspot.com/2016/04/mobility-in-contiki-2.html

Related

Can't get Adafruit Neopixel to work with Wemos D1

I am trying to get a very simple ESP8266 project to work but I keep failing and have no clue why.
These are my components:
Wemos D1 (ESP8266MOD)
WS2812B 5050 LED Stripe (2m with 60 LEDs/m)
5V 10A DC Power Supply
This is how I connected everything (I also tried multiple other pins on the controller)
Then I uploaded this code to the controller:
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#define PIN D2
#define NUMPIXELS 20
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 500;
void setup() {
pixels.begin();
}
void loop() {
pixels.clear();
for(int i=0;i<NUMPIXELS;i++){
pixels.setPixelColor(i, pixels.Color(0,150,0));
pixels.show();
delay(delayval);
}
}
Absolutely nothing happens. The LEDs remain dark.
I measured the voltage directly on the strip connectors and it's fine. I've got no oszilloscope, but I get varying voltages on the ESPs data pin, so I suppose that's also working as expected.
I also stumbled upon this article stating that the signal voltage has to be at least 60% of the voltage of the stripe while my controller works with 3.3V (seee Datasheet). So I thought this might be part of the problem and tried it again wiht another power supply providing araound 3.8V at max. 5A with the same result. I am running out of ideas. Maybe you have got some for me.

Compile the Robot Control Library for a different beaglebone cape

How should I go about modifying and/or compiling the Robot Control Library for use with a different beaglebone cape that uses slightly different pin assignments?
My primary reason for wanting to re-use the Robot Control Library is the ability to read a fourth encoder via the PRU. Beyond that, I only need access to the encoder and pwm modules.
TL;DR
Modifying the PRU firmware to read the encoder signal from a different pin was easy. Figuring out how to assemble a working device tree for the combination of features I needed was way harder.
I would welcome any feedback on how I should have done this, or how I could improve upon what I currently have.
Robot Control Library + Motor Cape
The Robotics Cape and the BeagleBone Blue provide a turnkey solution for servo controlling four motors,
IFF you are satisfied with driving them at 8V (e.g. a 2S LIPO battery). The Motor Cape can handle a
higher drive voltage (and more current), but does not include encoders. Plugging encoders into the P8 & P9
headers on the Motor Cape is simple enough, but the BeagleBone itself only has 3 encoder counters (eQEP).
The Robot Control Library solves this problem by reading the fourth encoder with PRU0. However, some of the
pins conflict between the Motor Cape and what the Robot Control Library expects on the Robotics Cape.
So, how hard could it be to use the Robot Control Library to read encoders and drive motors with a slightly
different pinout on the Motor Cape? Probably not difficult at all if you are already competent with BeagleBone
device tree overlays, which I am not...
It all starts with a plan -- Pin Selection
Pin
PRU Bit
Robotics Cape
Motor Cape
P8_15
15
Enc 4B
--
P8_16
14
Enc 4A
M2 Dir
P9_25
7
IMU
--
The Robot Control Library expects the fourth encoder to show up on P8_15 and P8_16, but the
Motor Cape has P8_16 wired as a direction signal. There are only 12 pins than be configured
as inputs to PRU0 and I eventually selected P9_25 because I did not need the IMU functionality.
The best reference I found for what pins can be used for what purposes were these pdfs:
https://ofitselfso.com/BeagleNotes/BeagleboneBlackP8HeaderPinMuxModes.pdf
https://ofitselfso.com/BeagleNotes/BeagleboneBlackP9HeaderPinMuxModes.pdf
The Easy Part -- Modifying the PRU Code
The Robot Control Library defines the encoder signal input bits in pru_firmware/src/pur0-encoder.asm as
; Encoder counting definitions
; these pin definitions are specific to SD-101D Robotics Cape
.asg r0, OLD ; keep last known values of chA and B in memory
.asg r1, EXOR ; place to store the XOR of old with new AB vals
.asg 14, A
.asg 15, B
This can be modified to look for the A channel on bit 7 (of register 31, which is used for all inputs) as
; Encoder counting definitions
; these pin definitions are specific to SD-101D Robotics Cape
.asg r0, OLD ; keep last known values of chA and B in memory
.asg r1, EXOR ; place to store the XOR of old with new AB vals
.asg 07, A
.asg 15, B
N.B. The PRU firmware has to be separately compiled by by running make and sudo make install
inside the pru_firmware directory. It is not compiled automatically as part as part of building the rest
of the library from the top-level Makefile.
Helpful Tip: What version am I actually running?
There are instructions on modifying the repored version of librobotcontrol in
library/version_updating_howto.txt. I followed these instructions to create my own
"private" version number so that I could confirm that I was actually running my modified
version of the libray. This version is reported by rc_test_drivers.
However... as noted above, the PRU firmware was not getting compiled by the top-level Makefile,
so for a while I was running my "new" version of librobotcontrol with "old" firmware in the PRU.
The Part that Almost Worked -- The Device Tree
I found references in both the documentation and code for librobotcontrol that device tree overlays
were no longer needed because the Robotics Cape used its own device tree.
The overlay is deprecated now, instead the cape gets its own complete device tree.
I also observed that running the recommended configure_robotics_dt.sh replaced /boot/uEnv.txt with
the following simplified version that loads a single device tree binary (.dtb)
uname_r=4.19.94-ti-r42
dtb=am335x-boneblack-roboticscape.dtb
cmdline=coherent_pool=1M
My favorite reference that I found for general information about the device tree, pinmux, etc was
http://www.ofitselfso.com/BeagleNotes/AboutTheDeviceTree.pdf However, I now realize that some of the
details are a bit out of date, so be careful.
Because I had very little idea of where else to start, I set out to modify the robotics cape device tree
just enough to eliminate the conflicts with the Motor Cape. I forked and cloned
https://github.com/beagleboard/BeagleBoard-DeviceTrees and created two new files
am335x-boneblack-custom.dts
copy of am335x-boneblack-roboticscape.dts
changed model to make the new device tree recognizable
changed #include to point to am335x-custom.dtsi instead of am335x-roboticscape.dtsi
am335x-custom.dtsi
copy of am335x-roboticscape.dtsi
deleted a whole bunch of stuff I thought I didn't need anymore
routed P9_25 (instead of P8_16) to PRU0
Before
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x038 0x36 /* P8_16,PRU0_r31_14,MODE6 */
After
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x1ac 0x36 /* P9_25,PRU0_r31_7,MODE6 */
After compiling and installing the modified device trees (make, sudo make install in the
BeagleBoard-DeviceTrees repo), I modified /boot/uEnv.txt to call my new custom device tree
uname_r=4.19.94-ti-r42
dtb=am335x-boneblack-custom.dtb
cmdline=coherent_pool=1M
I was able to boot the BeagleBone with no cape installed, plug encoders directly into the desired pins
on P8_and P9 (including enc4a on P9_25) and read all four encoders using sudo rc_test_encoders.
I thought I had won and went to bed...
Motor Cape Won't Boot
After a good night's sleep, I plugged the Motor Cape onto the BeagleBone expecting nothing to change since
I was only passing encoder signals directly through the P8 and P9 headers. I thought the next step would be
to make similar tweaks to a few of the pwm direction pins.
However, the BeagleBone refused to boot my custom device tree with the MotorCape installed. I went back to
the "standard" am335x-boneblack-roboticscape.dtb device tree and observed that it would not boot either with
the Motor Cape intalled. I also became suspicious that the "factory" installation of the Robotics Cape might have
been using overlays after all
I had been torn from the beginning about whether I should be starting from the Robotics Cape device tree and removing
things I did not need in order to eliminate resource conflicts, versus starting with the "naked" BeagleBone device tree
and adding the things that I did need. Whether accurate or not, in my mind that kind-of mapped into trying to specify
a full device tree versus providing an overlay to apply on top of the base device tree. The latter seemed like
the conceptually more correct path, so once the Motor Cape failed to boot with the robotics-cape-derived device tree,
I decided to bite the bullet and try to figure out device tree overlays.
Unanswered Questions
[ ] Why won't the BB boot from am335x-boneblack-roboticscape.dtb with the motor cape installed? What is the actual error?
[ ] Does a "normal" installation of librobotcontrol install the simplified uEnv.txt above or does it use an overlay? Does it work?
I did not yet have USB-to-TTL serial cable that could fit under an installed cape, so I know very little about
why or how this was failing to boot.
The Part that Finally Worked -- Device Tree Overlays
I eventually figured out that the collection of device tree overlays is avialable both at
https://github.com/beagleboard/bb.org-overlays and in the v4.19.x-ti-overlays branch at
https://github.com/beagleboard/BeagleBoard-DeviceTrees. I suspect that this might be an
in-progress migration, but there was more documentation associated with the bb.org-overlays
repository so that is what I chose to use.
A few documentation links that I wish I had found earlier:
https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays
https://github.com/cdsteinkuehler/beaglebone-universal-io
https://vadl.github.io/beagleboneblack/2016/07/29/setting-up-bbb-gpio
I created forked, cloned, and branched the bb.org-overlays repo and created a new overlay at
src/arm/CustomCape-00A0.dts by hacking together pieces from BBORG_MOTOR-00A2.dts and RoboticsCape-00A0.dts
/*
* Device Tree Overlay for custom cape trying to reuse Robot Control Library's
* reading of 4x optical encoders.
*/
/*
pinmux control byte map courtesy of http://beaglebone.cameon.net/
Bit 5: 1 - Input, 0 - Output
Bit 4: 1 - Pull up, 0 - Pull down
Bit 3: 1 - Pull disabled, 0 - Pull enabled
Bit 2 \
Bit 1 |- Mode
Bit 0 /
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone-black";
/* identification */
part-number = "CustomCape";
/* version */
version = "00A0";
exclusive-use =
"P8.11", /*QEP_2B*/
"P8.12", /*QEP_2A*/
"P8.16", /*PRU_ENCODER_A*/
"P8.33", /*QEP_1B*/
"P8.35", /*QEP_1A*/
"P9.27", /*QEP_0B*/
"P9.41", /*MOT_STBY*/
"P9.42"; /*QEP_0A*/
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
fragment#0 {
target-path="/";
__overlay__ {
chosen {
overlays {
CustomCape-00A0 = __TIMESTAMP__;
};
};
};
};
fragment#1 {
target = <&am33xx_pinmux>;
__overlay__ {
/****************************************
* pinmux helper
****************************************/
mux_helper_pins: pins {
pinctrl-single,pins = <
/* EQEP */
0x1A0 0x31 /* P9_42,EQEP0A, MODE1 */
0x1A4 0x31 /* P9_27,EQEP0B, MODE1 */
0x0D4 0x32 /* P8_33,EQEP1B, MODE2 */
0x0D0 0x32 /* P8_35,EQEP1A, MODE2 */
0x030 0x34 /* P8_12,EQEP2A_in, MODE4 */
0x034 0x34 /* P8_11,EQEP2B_in, MODE4 */
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x1ac 0x36 /* P9_25,PRU0_r31_7,MODE6 */
>;
};
};
};
/****************************************
Pinmux Helper
activates the pinmux helper list of pin modes
****************************************/
fragment#2 {
target = <&ocp>;
__overlay__ {
test_helper: helper {
compatible = "bone-pinmux-helper";
pinctrl-names = "default";
pinctrl-0 = <&mux_helper_pins>;
status = "okay";
};
};
};
/*
* Free up the pins used by the cape from the pinmux helpers.
*/
fragment#3 {
target = <&ocp>;
__overlay__ {
P8_11_pinmux { status = "disabled"; }; /* enc3b */
P8_12_pinmux { status = "disabled"; }; /* enc3a */
P8_15_pinmux { status = "disabled"; }; /* enc4b */
P8_33_pinmux { status = "disabled"; }; /* enc0 */
P8_35_pinmux { status = "disabled"; }; /* enc0 */
P9_25_pinmux { status = "disabled"; }; /* enc4a */
P9_27_pinmux { status = "disabled"; }; /* enc1b */
P9_92_pinmux { status = "disabled"; }; /* enc1a */
};
};
/****************************************
Encoders
****************************************/
fragment#9 {
target = <&eqep0>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
fragment#10 {
target = <&eqep1>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
fragment#11 {
target = <&eqep2>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
/****************************************
PRU
****************************************/
fragment#31 {
target = <&pruss>;
__overlay__ {
status = "okay";
};
};
};
I added my custom overlay to /boot/uEnv.txt and disabled the video and audio overlays
uname_r=4.19.94-ti-r42
#uuid=
#dtb=
###U-Boot Overlays###
###Documentation: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays
###Master Enable
enable_uboot_overlays=1
###
###Additional custom capes
uboot_overlay_addr4=/lib/firmware/CustomCape-00A0.dtbo
###
###Custom Cape
#dtb_overlay=/lib/firmware/<file8>.dtbo
###
###Disable auto loading of virtual capes (emmc/video/wireless/adc)
#disable_uboot_overlay_emmc=1
disable_uboot_overlay_video=1
disable_uboot_overlay_audio=1
#disable_uboot_overlay_wireless=1
#disable_uboot_overlay_adc=1
###
###PRUSS OPTIONS
###pru_rproc (4.19.x-ti kernel)
uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo
###
###Cape Universal Enable
enable_uboot_cape_universal=1
###
###U-Boot Overlays###
cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet
I make no claims of optimality or even correctness, but this configuration boots with or without the Motor Cape
installed and I can read all four encoders with rc_test_encoders. When the Motor Cape is installed, uBoot
is correctly picking up and applying the BBORG_MOTOR-00A2 overlay. I honestly thought that I would need a lot more
configuration of the PRU to get the PRU-based encoder counter from the Robot Control Library working, but this seeems
to do the trick.
I would welcome any feedback on how I should have done this, or how I could improve upon what I currently have.
Helpful Tip: Watch the serial terminal!
I am embarrassed that I even attempted to debug device tree booting issues without first having a serial terminal
open to the beaglebone so that I could observe the boot sequence. With the help of some 5-minute epoxy, I was
eventually able to make a 90-degree header to bring the JTAG port out from under an installed cape.
https://elinux.org/Beagleboard:BeagleBone_Black_Serial

Clang: How to get the macro name used for size of a constant size array declaration

TL;DR;
How to get the macro name used for size of a constant size array declaration, from a callExpr -> arg_0 -> DeclRefExpr.
Detailed Problem statement:
Recently I started working on a challenge which requires source to source transformation tool for modifying
specific function calls with an additional argument. Reasearching about the ways i can acheive introduced me
to this amazing toolset Clang. I've been learning how to use different tools provided in libtooling to
acheive my goal. But now i'm stuck at a problem, seek your help here.
Considere the below program (dummy of my sources), my goal is to rewrite all calls to strcpy
function with a safe version of strcpy_s and add an additional parameter in the new function call
i.e - destination pointer maximum size. so, for the below program my refactored call would be like
strcpy_s(inStr, STR_MAX, argv[1]);
I wrote a RecursiveVisitor class and inspecting all function calls in VisitCallExpr method, to get max size
of the dest arg i'm getting VarDecl of the first agrument and trying to get the size (ConstArrayType). Since
the source file is already preprocessed i'm seeing 2049 as the size, but what i need is the macro STR_MAX in
this case. how can i get that?
(Creating replacements with this info and using RefactoringTool replacing them afterwards)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define STR_MAX 2049
int main(int argc, char **argv){
char inStr[STR_MAX];
if(argc>1){
//Clang tool required to transaform the below call into strncpy_s(inStr, STR_MAX, argv[1], strlen(argv[1]));
strcpy(inStr, argv[1]);
} else {
printf("\n not enough args");
return -1;
}
printf("got [%s]", inStr);
return 0;
}
As you noticed correctly, the source code is already preprocessed and it has all the macros expanded. Thus, the AST will simply have an integer expression as the size of array.
A little bit of information on source locations
NOTE: you can skip it and proceed straight to the solution below
The information about expanded macros is contained in source locations of AST nodes and usually can be retrieved using Lexer (Clang's lexer and preprocessor are very tightly connected and can be even considered one entity). It's a bare minimum and not very obvious to work with, but it is what it is.
As you are looking for a way to get the original macro name for a replacement, you only need to get the spelling (i.e. the way it was written in the original source code) and you don't need to carry much about macro definitions, function-style macros and their arguments, etc.
Clang has two types of different locations: SourceLocation and CharSourceLocation. The first one can be found pretty much everywhere through the AST. It refers to a position in terms of tokens. This explains why begin and end positions can be somewhat counterintuitive:
// clang::DeclRefExpr
//
// ┌─ begin location
foo(VeryLongButDescriptiveVariableName);
// └─ end location
// clang::BinaryOperator
//
// ┌─ begin location
int Result = LHS + RHS;
// └─ end location
As you can see, this type of source location points to the beginning of the corresponding token. CharSourceLocation on the other hand, points directly to the characters.
So, in order to get the original text of the expression, we need to convert SourceLocation's to CharSourceLocation's and get the corresponding text from the source.
The solution
I've modified your example to show other cases of macro expansions as well:
#define STR_MAX 2049
#define BAR(X) X
int main() {
char inStrDef[STR_MAX];
char inStrFunc[BAR(2049)];
char inStrFuncNested[BAR(BAR(STR_MAX))];
}
The following code:
// clang::VarDecl *VD;
// clang::ASTContext *Context;
auto &SM = Context->getSourceManager();
auto &LO = Context->getLangOpts();
auto DeclarationType = VD->getTypeSourceInfo()->getTypeLoc();
if (auto ArrayType = DeclarationType.getAs<ConstantArrayTypeLoc>()) {
auto *Size = ArrayType.getSizeExpr();
auto CharRange = Lexer::getAsCharRange(Size->getSourceRange(), SM, LO);
// Lexer gets text for [start, end) and we want him to grab the end as well
CharRange.setEnd(CharRange.getEnd().getLocWithOffset(1));
auto StringRep = Lexer::getSourceText(CharRange, SM, LO);
llvm::errs() << StringRep << "\n";
}
produces this output for the snippet:
STR_MAX
BAR(2049)
BAR(BAR(STR_MAX))
I hope this information is helpful. Happy hacking with Clang!

Tracking stack size during application execution

I am running an application on an embedded (PowerPC 32 bit) system where there is a stack size limitation of 64K. I am experiencing some occasional crashes because of stack overflow.
I can build the application also for a normal Linux system (with some minor little changes in the code), so I can run an emulation on my development environment.
I was wondering which is the best way to find the methods that exceed the stack size limitation and which is the stack frame when this happens (in order to perform some code refactoring).
I've already tried Callgrind (a Valgrind tool), but it seems not to be the right tool.
I'm looking more for a tool than changes in the code (since it's a 200K LOC and 100 files project).
The application is entirely written in C++03.
While it seems that there should be an existing tool for this, I would approach it by writing a small macro and adding it to the top of suspected functions:
char *__stack_root__;
#define GUARD_SIZE (64 * 1024 - 1024)
#define STACK_ROOT \
char __stack_frame__; \
__stack_root__ = &__stack_frame__;
#define STACK_GUARD \
char __stack_frame__; \
if (abs(&__stack_frame__ - __stack_root__) > GUARD_SIZE) { \
printf("stack is about to overflow in %s: at %d bytes\n", __FUNCTION__, abs(&__stack_frame__ - __stack_root__)); \
}
And here how to use it:
#include <stdio.h>
#include <stdlib.h>
void foo(int);
int main(int argc, char** argv) {
STACK_ROOT; // this macro records the top of the bottom of the thread's stack
foo(10000);
return 0;
}
void foo(int x) {
STACK_GUARD; // this macro checks if we're approaching the end of memory available for stack
if (x > 0) {
foo(x - 1);
}
}
couple notes here:
this code assumes single thread. If you have multiple threads, you need to keep track of individual __stack_frame__ variables, one per thread. Use thread local storage for this
using abs() to make sure the macro works both when PowerPC grows its stack up, as well as down (it can: depends on your setup)
adjust the GUARD_SIZE to your liking, but keep it smaller than the max size of your stack on the target

What are ‘I Space’ and ‘D Space’ on osx and the difference between them

In sys/ptrace.h, i saw something like:
#define PT_READ_I 1 /* read world in child's I space*/
#define PT_READ_D 2 /* read world in child's D space*/
#define PT_READ_U 3 /* read world in child's user structure*/
What are ‘I Space’ and ‘D Space’ and 'user structure'?
Quoting the man page:
Traditionally, ptrace() has
allowed for machines with distinct address spaces for
instruction and data, which is why there are two requests:
conceptually, PT_READ_I reads from the instruction space
and PT_READ_D reads from the data space. In the current
NetBSD implementation, these two requests are completely
identical.
Now about PT_READ_U:
This space contains the registers and other information about the
process; its layout corresponds to the user structure in the system.

Resources