Xenomai rtdm_clock_read measure - c

I'm really a newbie when it comes to Xenomai and I want to measure the times between two points.
I want first to send a pulse of 10µs.
After that, I wait till I have an interrupt.
I want to measure the time between the pulse and the interrupt.
I use the 'rtmd_clock_read()' function. So the type that it return is 'nanosecs_abs_t '. When I use this I can't lod the module anymore and get this when I do a 'make'.
WARNING: "__aeabi_uldivmod" [...] undefined!
If I want to run it, with 'insmod', it says this:
Unknow symbol in module
This is my Makefile
EXTRA_CFLAGS := -I /usr/xenomai/include/
ifneq (${KERNELRELEASE},)
obj-m += oef1.o
else
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/cross/rpi/bin/arm-linux-
KERNEL_DIR = /usr/src/linux
MODULE_DIR := $(shell pwd)
CFLAGS := -Wall -g
.PHONY: all
all:: modules
.PHONY: modules
modules:
${MAKE} -C ${KERNEL_DIR} SUBDIRS=${MODULE_DIR} modules
XENOCONFIG=/usr/xenomai/bin/xeno-config
.PHONY: clean
clean::
rm -f *.o .*.o .*.o.* *.ko .*.ko *.mod.* .*.mod.* .*.cmd *~
rm -f Module.symvers Module.markers modules.order
rm -rf .tmp_versions
endif
run: oef1.ko
insmod oef1.ko
stop:
rmmod oef1
this is my .c file.
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <rtdm/rtdm_driver.h>
//define pins for the ultrasonic sensor
#define TRIGGER 4 //GPIO_0, pin 3 on the pi
#define ECHO 15 //GPIO_1, pin 5 on the pi
//Define the outputs for the leds
///blablabla
//define the time the trigger needs to be high
#define TRIGGER_PERIOD 10000//10us
#define SLEEP_TASK_TRIGGER 1000000000 //1s
//task for sending trigger pulse
static rtdm_task_t trigger_task;
//needed i n multiple operactions
static rtdm_mutex_t periode_mutex;
//timer to get the distance of the sensor
int end = 0;
nanosecs_abs_t time1=0;
nanosecs_abs_t time2=0;
int centimeter=0;
nanosecs_abs_t difTime=0;
//for GPIO interrupt
static rtdm_irq_t irq_rtdm;
static int numero_interruption;
static void triggertask(void * p)
{
printk("first time in trigger");
int value=0;
while(!end)
{
printk("trigger \n");
gpio_set_value(TRIGGER,1);
rtdm_task_sleep(TRIGGER_PERIOD);
gpio_set_value(TRIGGER,0);
rtdm_task_wait_period();
rtdm_mutex_lock(&periode_mutex);
time1 = rtdm_clock_read();
rtdm_mutex_unlock(&periode_mutex);
//printk("tijd1 %d\n",time1);
rtdm_task_sleep(SLEEP_TASK_TRIGGER);
}
}
static int handler_interruption(rtdm_irq_t * irq)
{
printk("irq\n");
//stop timer, get difference
rtdm_mutex_lock(&periode_mutex);
time2 = rtdm_clock_read();
//printk("tijd2 %d\n",time2);
difTime = time2-time1;
centimeter = (difTime/1000)/56;
rtdm_mutex_unlock(&periode_mutex);
printk("centimer: ");
printk("%d",centimeter);
return RTDM_IRQ_HANDLED;
}
static int __init init_sensor(void)
{
int err;
rtdm_printk("initsensor");
//error handling nog toevoegen
numero_interruption = gpio_to_irq(ECHO);
if((err = gpio_request(ECHO, THIS_MODULE->name))!=0)
{
return err;
}
if((err = gpio_direction_input(ECHO)) !=0)
{
gpio_free(ECHO);
return err;
}
irq_set_irq_type(numero_interruption, IRQF_TRIGGER_RISING);
if((err=rtdm_irq_request(& irq_rtdm, numero_interruption,handler_interruption,RTDM_IRQTYPE_EDGE,THIS_MODULE->name,NULL))!= 0)
{
gpio_free(ECHO);
gpio_free(TRIGGER);
return err;
}
rtdm_irq_enable(& irq_rtdm);
rtdm_mutex_init(&periode_mutex);
if((err = gpio_request(TRIGGER,THIS_MODULE->name))!=0)
{
return err;
}
if((err = gpio_direction_output(TRIGGER,1))!=0)
{
gpio_free(TRIGGER);
return err;
}
err = rtdm_task_init(&trigger_task,"send_trigger_task",triggertask,NULL,99,0);
if(err !=0)
{
gpio_free(TRIGGER);
}
return err;
}
static void __exit exit_sensor(void)
{
//stop
end = 1;
rtdm_task_join_nrt(&trigger_task,100);
rtdm_irq_disable(& irq_rtdm);
rtdm_irq_free(& irq_rtdm);
gpio_free(TRIGGER);
gpio_free(ECHO);
}
module_init(init_sensor);
module_exit(exit_sensor);
MODULE_LICENSE("GPL");
thank you guys!

Symbol __aeabi_uldivmod is required for modulo operation on 64-bit integers. Call for this function is automatically generated by gcc when it encounters operations of such sort. While user-space library (libgcc) implements this function, kernel doesn't implement it automatically for all architectures.
When divisor is predefined constant, division/module operation may be replaced with multiplication on magic number and shift. Here you may calculate magic number for your case.

Related

how to stub fgets in C while using Google Unit Test

I have currently been assigned to do unit tests on some problems that I've done during an introductory bootcamp, and I'm having problems understanding the concept of 'stub' or 'mock'.
I'm using Google Unit Test, and the problems from the bootcamp are solved in C.
int validate_input(uint32_t * input_value) {
char input_buffer[1024] = {0};
char * endptr = NULL;
int was_read_correctly = 1;
printf("Give the value for which to print the bits: ");
/*
* Presuming wrong input from user, it does not signal:
* - number that exceeds the range of uint_32 (remains to be fixed)
* For example: 4294967295 is the max value of uint_32 ( and this can be also confirmed by the output )
* If bigger numbers are entered the actual value seems to reset ( go back to 0 and upwards.)
*/
if (NULL == fgets(input_buffer, 1024, stdin)) {
was_read_correctly = 0;
} else {
if ('-' == input_buffer[0]) {
fprintf(stderr, "Negative number not allowed.\n");
was_read_correctly = 0;
}
}
errno = 0;
if (1 == was_read_correctly) {
* input_value = strtol(input_buffer, & endptr, 10);
if (ERANGE == errno) {
fprintf(stderr, "Sorry, this number is too small or too large.\n");
was_read_correctly = 0;
} else if (endptr == input_buffer) {
fprintf(stderr, "Incorrect input.\n(Entered characters or characters and digits.)\n");
was_read_correctly = 0;
} else if ( * endptr && '\n' != * endptr) {
fprintf(stderr, "Input didn't get wholely converted.\n(Entered digits and characters)\n");
was_read_correctly = 0;
}
} else {
fprintf(stderr, "Input was not read correctly.\n");
was_read_correctly = 0;
}
return was_read_correctly;
}
How should I think/plan the process of stubbing a function like fgets/malloc in C? And, if it isn't too much, how a function like this should be thought to test?
Disclaimer: This is just one way to mock C functions for GoogleTest. There are other methods for sure.
The problem to mock C functions lays in the way GoogleTest works. All its cool functionality is based on deriving a C++ class to mock and overriding its methods. These methods must be virtual, too. But C function are no members of any class, left alone of being virtual.
The way we found and use with success it to provide a kind of wrapper class that includes methods that have the same prototype as the C functions. Additionally this class holds a pointer to an instance of itself as a static class variable. In some sense this resembles the Singleton pattern, with all its characteristics, for good or bad.
Each test instantiates an object of this class and uses this object for the common checks.
Finally the C functions are implemented as stubs that call the single instance's method of the same kind.
Let's say we have these C functions:
// cfunction.h
#ifndef C_FUNCTION_H
#define C_FUNCTION_H
extern "C" void cf1(int p1, void* p2);
extern "C" int cf2(void);
#endif
Then the header file for the mocking class is:
// CFunctionMock.h
#ifndef C_FUNCTION_MOCK_H
#define C_FUNCTION_MOCK_H
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "cfunction.h"
class CFunctionMock
{
public:
static CFunctionMock* instance;
CFunctionMock() {
instance = this;
}
~CFunctionMock() {
instance = nullptr;
}
MOCK_METHOD(void, cf1, (int p1, void* p2));
MOCK_METHOD(int, cf2, (void));
};
#endif
And this is the implementation of the mocking class, including the replacing C functions. All the functions check that the single instance exists.
// CFunctionMock.cpp
#include "CFunctionMock.h"
CFunctionMock* CFunctionMock::instance = nullptr;
extern "C" void cf1(int p1, void* p2) {
ASSERT_NE(CFunctionMock::instance, nullptr);
CFunctionMock::instance->cf1(p1, p2);
}
extern "C" int cf2(void) {
if (CFunctionMock::instance == nullptr) {
ADD_FAILURE() << "CFunctionMock::instance == nullptr";
return 0;
}
return CFunctionMock::instance->cf2();
}
On non-void function you can't use ASSERT_NE because it quits on an error with a simple return. Therefore the check for an existing instance is a bit more elaborated. You should think of a good default value to return, too.
Now we get to write some test.
// SomeTest.cpp
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::_;
using ::testing::Return;
#include "CFunctionMock.h"
#include "module_to_test.h"
TEST(AGoodTestSuiteName, AndAGoodTestName) {
CFunctionMock mock;
EXPECT_CALL(mock, cf1(_, _))
.Times(0);
EXPECT_CALL(mock, cf2())
.WillRepeatedly(Return(23));
// any call of module_to_test that calls (or not) the C functions
// any EXPECT_...
}
EDIT
I was reading the question once more and came to the conclusion that a more direct example is necessary. So here we go! I like to use as much of the magic behind Googletest because it makes extensions so much easier. Working around it feels like working against it.
Oh, my system is Windows 10 with MinGW64.
I'm a fan of Makefiles:
TESTS := Test
WARNINGLEVEL := -Wall -Wextra
CC := gcc
CFLAGS := $(WARNINGLEVEL) -g -O3
CXX := g++
CXXFLAGS := $(WARNINGLEVEL) -std=c++11 -g -O3 -pthread
LD := g++
LDFLAGS := $(WARNINGLEVEL) -g -pthread
LIBRARIES := -lgmock_main -lgtest -lgmock
GTESTFLAGS := --gtest_color=no --gtest_print_time=0
all: $(TESTS:%=%.exe)
run: all $(TESTS:%=%.log)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
%.o: %.cpp
$(CXX) $(CXXFLAGS) -I./include -c $< -o $#
%.exe: %.o
$(LD) $(LDFLAGS) $^ -L./lib $(LIBRARIES) -o $#
%.log: %.exe
$< $(GTESTFLAGS) > $# || type $#
Test.exe: module_to_test.o FgetsMock.o
These Makefiles make it easy to add more tests, modules, anything, and document all options. Extend it to your liking.
Module to Test
To get no warning, I had to extend the provided source:
// module_to_test.c
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "module_to_test.h"
// all the rest is as in the OP's source...
And of course we need a header file:
// module_to_test.h
#include <stdint.h>
int validate_input(uint32_t *input_value);
The Mock Class
The mock class is modelled after the example above. Do enable "feeding" the string I added an parameterized action.
// FgetsMock.h
#ifndef FGETS_MOCK_H
#define FGETS_MOCK_H
#include <cstring>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
ACTION_P(CopyFromSource, source)
{
memcpy(arg0, source, arg1);
}
class FgetsMock
{
public:
static FgetsMock* instance;
FgetsMock()
{
instance = this;
}
~FgetsMock()
{
instance = nullptr;
}
MOCK_METHOD(char*, fgets, (char*, int, FILE*));
};
#endif
Its implementation file is straight forward and provides the mocked C function.
// FgetsMock.cpp
#include <stdio.h>
#include "FgetsMock.h"
FgetsMock* FgetsMock::instance = nullptr;
extern "C" char* fgets(char* str, int num, FILE* stream)
{
if (FgetsMock::instance == nullptr)
{
ADD_FAILURE() << "FgetsMock::instance == nullptr";
return 0;
}
return FgetsMock::instance->fgets(str, num, stream);
}
Implementing Some Tests
Here are some examples for tests. Unfortunately the module-to-test uses stdout and stderr that are not so simple to catch and test. You might like to read about "death tests" or provide your own method of redirection. In the core, the design of the function is not that good, because it did not take testing into account.
// Test.cpp
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::Ge;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::ReturnArg;
#include "FgetsMock.h"
extern "C"
{
#include "module_to_test.h"
}
TEST(ValidateInput, CorrectInput)
{
const char input[] = "42";
const int input_length = sizeof input;
FgetsMock mock;
uint32_t number;
EXPECT_CALL(mock, fgets(NotNull(), Ge(input_length), stdin))
.WillOnce(DoAll(
CopyFromSource(input),
ReturnArg<0>()
));
int result = validate_input(&number);
EXPECT_EQ(result, 1);
EXPECT_EQ(number, 42U);
}
TEST(ValidateInput, InputOutputError)
{
FgetsMock mock;
uint32_t dummy;
EXPECT_CALL(mock, fgets(_, _, _))
.WillOnce(Return(nullptr));
int result = validate_input(&dummy);
EXPECT_EQ(result, 0);
}
TEST(ValidateInput, NegativeInput)
{
const char input[] = "-23";
const int input_length = sizeof input;
FgetsMock mock;
uint32_t dummy;
EXPECT_CALL(mock, fgets(NotNull(), Ge(input_length), stdin))
.WillOnce(DoAll(
CopyFromSource(input),
ReturnArg<0>()
));
int result = validate_input(&dummy);
EXPECT_EQ(result, 0);
}
TEST(ValidateInput, RangeError)
{
const char input[] = "12345678901";
const int input_length = sizeof input;
FgetsMock mock;
uint32_t dummy;
EXPECT_CALL(mock, fgets(NotNull(), Ge(input_length), stdin))
.WillOnce(DoAll(
CopyFromSource(input),
ReturnArg<0>()
));
int result = validate_input(&dummy);
EXPECT_EQ(result, 0);
}
TEST(ValidateInput, CharacterError)
{
const char input[] = "23fortytwo";
const int input_length = sizeof input;
FgetsMock mock;
uint32_t dummy;
EXPECT_CALL(mock, fgets(NotNull(), Ge(input_length), stdin))
.WillOnce(DoAll(
CopyFromSource(input),
ReturnArg<0>()
));
int result = validate_input(&dummy);
EXPECT_EQ(result, 0);
}
Building and Running the Tests
This is the output of my (Windows) console when building freshly and testing:
> make run
gcc -Wall -Wextra -g -O3 -c module_to_test.c -o module_to_test.o
g++ -Wall -Wextra -std=c++11 -g -O3 -pthread -I./include -c FgetsMock.cpp -o FgetsMock.o
g++ -Wall -Wextra -std=c++11 -g -O3 -pthread -I./include -c Test.cpp -o Test.o
g++ -Wall -Wextra -g -pthread Test.o module_to_test.o FgetsMock.o -L./lib -lgmock_main -lgtest -lgmock -o Test.exe
Test.exe --gtest_color=no --gtest_print_time=0 > Test.log || type Test.log
Input was not read correctly.
Negative number not allowed.
Input was not read correctly.
Sorry, this number is too small or too large.
Input didn't get wholely converted.
(Entered digits and characters)
rm Test.o
You see the output of stderr of the C function.
And this is the recorded log, see the Makefile how it is produced.
Running main() from gmock_main.cc
[==========] Running 5 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 5 tests from ValidateInput
[ RUN ] ValidateInput.CorrectInput
Give the value for which to print the bits: [ OK ] ValidateInput.CorrectInput
[ RUN ] ValidateInput.InputOutputError
Give the value for which to print the bits: [ OK ] ValidateInput.InputOutputError
[ RUN ] ValidateInput.NegativeInput
Give the value for which to print the bits: [ OK ] ValidateInput.NegativeInput
[ RUN ] ValidateInput.RangeError
Give the value for which to print the bits: [ OK ] ValidateInput.RangeError
[ RUN ] ValidateInput.CharacterError
Give the value for which to print the bits: [ OK ] ValidateInput.CharacterError
[----------] Global test environment tear-down
[==========] 5 tests from 1 test suite ran.
[ PASSED ] 5 tests.
Because of the output on stdout it is mixed up with Googletest's output.
I have managed to solve this issue in the following way:
header file for the stub function:
#ifndef STUBS_H_
#define STUBS_H_
#include "../src/p1.h"
char* fgets_stub(char *s, int size, FILE *stream);
#define fgets fgets_stub
#include "../src/p1.c"
char* fgets_RET;
#endif
implementation of stub function:
#include "stubs.h"
char* fgets_stub(char *s, int size, FILE *stream)
{
if (NULL != fgets_RET)
{
strcpy(s,fgets_RET);
}
return fgets_RET;
}
how to test in test.cpp:
TEST(ValidateInput,CorrectionTest)
{
uint32_t tester = 0;
char* dummy_char = new char[NUM_OF_BITS];
strcpy(dummy_char,"39131");
cout<<dummy_char;
fgets_RET = dummy_char;
ASSERT_EQ(1,validate_input(&tester));
}
if the person that tests wishes to force NULL return of fgets:
TEST(ValidateInput,CorrectionTest)
{
uint32_t tester = 0;
fgets_RET = NULL;
ASSERT_EQ(0,validate_input(&tester));
}

FPGA Analog-to-Digital Conversion DE1-SOC

I have a DE1-SOC(Rev. C) running Linux. I am having problems accessing the onboard ADC. The input to all 8 channels is a 3V Pk-Pk sinusoidal signal. The onboard ADC is an AD7928 12-bit 8-channel ADC. The datasheet says that the ADC can handle bipolar signals, and gives the following circuit diagram:
AD7928 Bipolar Circuit Diagram
All eight channels need to be sampled continually. and the DE1-SOC datasheet specifies to set the channel one register to 1, which activates the automatic update option on the ADC. Here's my first attempt at the code. It compiles and runs but the values aren't correct, as the same signal that's being fed into the ADC is also being measured by my oscilloscope.
#include <inttypes.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/mman.h>
/* FPGA HPS BRIDGE BASE */
#define LW_BRIDGE_BASE (0xFF200000)
#define HW_REGS_BASE (0xFF200000)
#define HW_REGS_SPAN (0x00200000)
#define HW_REGS_MASK ( HW_REGS_SPAN - 1 )
/* HPS-2-FPGA AXI Bridge */
#define ALT_AXI_FPGASLVS_OFST (0xC0000000) // axi_master
#define HW_FPGA_AXI_SPAN (0x40000000) // Bridge span 1GB
#define HW_FPGA_AXI_MASK ( HW_FPGA_AXI_SPAN - 1 )
/* ADC REGISTER SPAN */
#define ADC_BASE (0x00004000)
/* ADC CHANNEL & UPDATE REGISTERS */
#define ADC_CH0_UPDATE (LW_BRIDGE_BASE+ADC_BASE)
#define ADC_CH1_AUTO_UPDATE (LW_BRIDGE_BASE+ADC_BASE+4) // Write 1 for continual ADC request
#define ADC_CH2 (LW_BRIDGE_BASE+ADC_BASE+8)
#define ADC_CH3 (LW_BRIDGE_BASE+ADC_BASE+12)
#define ADC_CH4 (LW_BRIDGE_BASE+ADC_BASE+16)
#define ADC_CH5 (LW_BRIDGE_BASE+ADC_BASE+20)
#define ADC_CH6 (LW_BRIDGE_BASE+ADC_BASE+24)
#define ADC_CH7 (LW_BRIDGE_BASE+ADC_BASE+28)
/* ADC REGISTER END */
#define ADC_END (0x0000001F)
int main() {
// Defining variables
void *virtual_base;
int fd;
volatile int *h2p_lw_adc_addr;
int i;
//Defining pointer for register
if((fd = open( "/dev/mem",(O_RDWR | O_SYNC ))) == -1) {
printf("ERROR: could not open \"/dev/mem\"...\n");
return(1);
}
virtual_base = mmap(NULL,HW_REGS_SPAN,(PROT_READ | PROT_WRITE),MAP_SHARED,fd,HW_REGS_BASE);
if(virtual_base == MAP_FAILED) {
printf("ERROR: mmap() failed...\n");
close(fd);
return(1);
}
h2p_lw_adc_addr = virtual_base + ((int)(LW_BRIDGE_BASE + ADC_BASE)&(int)(HW_REGS_MASK));
float Vref = 5.0;
float stepSize = Vref/4096.0;
/* Heading & Calculating Step Size/Resolution */
printf("*____________________________________*\n");
printf("* Setting up the AD7928 ADC *\n");
printf("*____________________________________*\n");
printf("Resolution for 5V Vref: %f[mV]\n", stepSize*1000);
// Setting up the ADC for bipolar signal
// ...
// Auto-update all channels continuously
*(int *)(h2p_lw_adc_addr + 4) = 1;
// Sample a single channel
// ...
/* Data Collection Attempt #1 */
int num = 5; // Number of samples?
unsigned int samples[num];
int channel = 16; // channel 4
for (i = 0; i < num; i++){
samples[i] = *(int *)(h2p_lw_adc_addr + channel);
}
if(munmap(virtual_base, HW_REGS_SPAN) != 0) {
printf("ERROR: munmap() failed...\n");
close(fd);
return(1);
}
close(fd);
return 0;
}
It gets cross-compiled using this Makefile:
C_SRC := adc.c
CFLAGS := -g -O0 -Wall
LDFLAGS := -lm
CROSS_COMPILE := arm-linux-gnueabihf-
CC := $(CROSS_COMPILE)gcc
NM := $(CROSS_COMPILE)nm
ifeq ($(or $(COMSPEC),$(ComSpec)),)
RM := rm -rf
else
RM := cs-rm -rf
endif
ELF ?= adc
OBJ := $(patsubst %.c,%.o,$(C_SRC))
.c.o:
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: all
all: $(ELF)
.PHONY:
clean:
$(RM) $(ELF) $(OBJ) $(OBJS) *.map *.objdump
$(ELF): $(OBJ) $(OBJS)
$(CC) $(CFLAGS) $(OBJ) $(OBJS) -o $# $(LDFLAGS)
$(NM) $# > $#.map
I'm a noobie when it comes to ADCs and DSP, but ideally, I would like to be able to continually measure all eight channels, recording the pk-pk (amplitude) of the incoming sine waves in each one, which will eventually be used for post-processing.
As of right now, the output for the five samples is always 0, except when I sample channel 1, then all five samples are 1, like so:
Samples [0]: 1
Samples [1]: 1
Samples [2]: 1
Samples [3]: 1
Samples [4]: 1
Even when I increase the number of samples, it's always 1 for Channel 1 and 0 for all the other channels.
I think my problem is probably a combination of my code and also maybe not having the buffering circuitry? (But I'm not handling the bipolar input only because I can set the DC offset on my signal generator so it's an all positive 3v pk-pk.)
Vref on the ADC is being fed an even 5V DC. I'm pretty lost right now, so any help or pointers would be greatly appreciated.
I bet that your problem is in the following lines:
> volatile int *h2p_lw_adc_addr;
>
> *(int *)(h2p_lw_adc_addr + 4) = 1;
>
> samples[i] = *(int *)(h2p_lw_adc_addr + channel);
Because h2p_lw_adc_addr is pointer to int, you will get wrong addresses from the later two lines.
When you add number N to the int pointer, the result pointer is N * sizeof(int) bigger than the int pointer.
Change the type of h2p_lw_adc_addr to char pointer to get quick fix:
volatile char *h2p_lw_adc_addr;
Or alternatively, you can change the offsets:
*(int *)(h2p_lw_adc_addr + 1) = 1;
int channel = 4; // channel 4
But in that case I propose to use int32_t or uint32_t instead on int:

Jprobe to 'do_execve' on Ubuntu 14 doesn't work but work on Ubuntu 12

I am trying to perform a hook to the function 'do_execve()' on Linux kernel using Jprobes, but I'm having issues with certain systems. I tried using this code I found online on an Ubuntu 12, 64 bit (Kernel Version 3.11):
Hook.c:
/* Trace do_execv. Taken basically from Documentation/kprobes.txt */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
/*
* Pre-entry point for do_execve.
*/
static int my_do_execve(char * filename,
char __user *__user *argv,
char __user *__user *envp,
struct pt_regs * regs)
{
printk("do_execve for %s from %s\n", filename, current->comm);
/* Always end with a call to jprobe_return(). */
jprobe_return();
/*NOTREACHED*/
return 0;
}
static struct jprobe my_jprobe = {
.entry = (kprobe_opcode_t *) my_do_execve
};
int init_module(void)
{
int ret;
my_jprobe.kp.addr =
(kprobe_opcode_t *) kallsyms_lookup_name("do_execve");
if (!my_jprobe.kp.addr) {
printk("Couldn't find %s to plant jprobe\n", "do_execve");
return -1;
}
if ((ret = register_jprobe(&my_jprobe)) <0) {
printk("register_jprobe failed, returned %d\n", ret);
return -1;
}
printk("Planted jprobe at %p, handler addr %p\n",
my_jprobe.kp.addr, my_jprobe.entry);
return 0;
}
void cleanup_module(void)
{
unregister_jprobe(&my_jprobe);
printk("jprobe unregistered\n");
}
MODULE_LICENSE("GPL");
Makefile:
# This is taken straight from Documentation/kprobes.txt
obj-m := trace-exec.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.mod.c *.ko *.o
The module worked as expected. It was first compiled correctly on the system, and then inserted with the function 'insmod' (with ROOT privileges). Running dmesg shows the correct output:
Planted Jprobes at [ADDRESS HERE], handler addr [ADDRESS HERE]
do_execve for /bin/sh from wcstatusd [PRINTED FOR ANY EXECUTED PROCESS]
The problem occurred when I tried the same code on Ubuntu 14, 64 bit (kernel version 3.13) system. I recompiled it on the system and inserted it just as I did on the previous system, however it didn't work this time. I don't get any errors, and the success message ("Planted jprobe at [ADDRESS WAS HERE], handler addr [ADDRESS WAS HERE]") is printed, but the 'do_execve' line isn't printed. I scanned Google but couldn't find an explanation or a solution. Any ideas?
NOTE: I also tried hooking 'do_fork()' on Ubuntu 14 and it worked! It's just something with 'do_execve()' and I can't figure what!
Definition for do_execve() is in exec.c
http://lxr.free-electrons.com/source/fs/exec.c?v=3.11#L1584
Here is the code for do_execve(). Just add a line after
int do_execve(struct filename *filename,const char __user *const __user *__argv,const char __user *const __user *__envp)
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct user_arg_ptr envp = { .ptr.native = __envp };
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
}
EXPORT_SYMBOL(do_execve); // Add this line.
This file will be in linux/fs/exec.c. Add the EXPORT_SYMBOL() line after the fuction.And after that do make, make install, and reboot.
Its almost like the hooking because we have to build and install the kernel again. Given that you are not intercepting the call by modifying the systemcall address at runtime.

Missing Symbol during Runtime in Over-The-Air Programming Code

I am currently working on developing over-the-air programming support on sky motes. Attached are the files that I have so far. I am basically trying to use the sky-shell-exec example to load my modified test-deluge.ce file onto the mote. I then try to run the test-deluge file using the shell 'exec' command as done in the sky-shell-exec example.
The final goal is to load both the test-deluge.ce and hello-world.ce compiled files onto the mote and then be able to 'exec' my test-deluge.ce file which would then find the stored hello-world.ce file and do a deluge_disseminate on it.
The progression of command I am running are as follows:
1) sudo make TARGET=sky clean CLEAN=symbols.?
2) sudo make sky-shell-exec.sky TARGET=sky
3) sudo make sky-shell-exec.sky CORE=sky-shell-exec.sky TARGET=sky
4) sudo make sky-shell-exec.upload CORE=sky-shell-exec.sky
5) sudo make compile-test-deluge-executable
6) sudo make upload-test-deluge-executable
7) sudo make login
8) ls (to see that the file made it)
9) exec test-deluge.ce
At this point I get a 'Symbol not found: deluge_disseminate' error
I believe the error is in the 'CORE=...' part of the make (in step 2 above). I have inspected the symbols.c file that is filled out in step 2 of the above and indeed there is no symbol for deluge_disseminate or any of the deluge commands for that matter that I recall.
For experimentation I tried the following:
sudo make test-deluge.sky TARGET=sky
sudo make test-deluge.sky CORE=test-deluge.sky TARGET=sky
and I find that the symbols for deluge are there, but I can't proceed to properly make sky-shell-exec file since doing so erases the symbols table and writes a new one.
I feel like there must be a simple fix to this as I can run hello-world from the sky-shell-exec example directory after following the above steps (1-9).
Does anyone have an idea of how to go about this?
NOTE: There may be a bug in my test-deluge.c where I try to open 'hello-world.sky' instead of 'hello-world.ce'...I wasn't really sure which one. I haven't been able to test this yet because of the missing symbol issue explained above, but if anyone would be willing to shed light on this issue as well I would be very appreciative.
Thanks
MAKEFILE
CONTIKI = ../..
ifndef TARGET
TARGET=sky
endif
APPS = deluge serial-shell
all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0
#all: $(CONTIKI_PROJECT)
%.tgz: %.ihex
mkdir $(basename $<) ; \
mv $< $(basename $<) ; \
echo $(basename $<)/$(basename $<).ihex 600 > $(basename $<)/runfile ; \
tar czf $# $(basename $<)
%.class: %.java
javac $(basename $<).java
viewrssi: ViewRSSI.class
make login | java ViewRSSI
include $(CONTIKI)/Makefile.include
%.shell-upload: %.ce
(echo; sleep 4; echo "~K"; sleep 4; \
echo "dec64 | write $*.ce | null"; sleep 4; \
../../tools/base64-encode < $<; sleep 4; \
echo ""; echo "~K"; echo "read $*.ce | size"; sleep 4) | make login
.PHONY: compile-test-deluge-executable upload-test-deluge-executable compile-hello-world-executable upload-test-deluge-executable
compile-hello-world-executable: hello-world.ce
echo Compiled Contiki executable: $<
upload-hello-world-executable: hello-world.shell-upload
echo Uploaded Contiki executable: $<
compile-test-deluge-executable: test-deluge.ce
echo Compiled Contiki executable: $<
upload-test-deluge-executable: test-deluge.shell-upload
echo Uploaded Contiki executable: $<
sky-shell-exec.c
#include "contiki.h"
#include "shell.h"
#include "serial-shell.h"
#include "deluge.h"
#include "dev/watchdog.h"
#include "net/rime.h"
#include "dev/cc2420.h"
#include "dev/leds.h"
#include "dev/light.h"
#include "dev/sht11.h"
#include "dev/battery-sensor.h"
#include "lib/checkpoint.h"
#include "net/rime/timesynch.h"
#include <stdio.h>
#include <string.h>
int (*keep_1)(void) = deluge_disseminate;
int (*keep_2)(void) = node_id_burn;
/*---------------------------------------------------------------------------*/
PROCESS(sky_shell_process, "Sky Contiki shell");
AUTOSTART_PROCESSES(&sky_shell_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(sky_shell_process, ev, data)
{
PROCESS_BEGIN();
serial_shell_init();
/*shell_blink_init();*/
shell_file_init();
shell_coffee_init();
/*shell_ps_init();*/
/*shell_reboot_init();*/
/*shell_rime_init();*/
/*shell_rime_netcmd_init();*/
/*shell_rime_ping_init();*/
/*shell_rime_debug_init();*/
/*shell_rime_sniff_init();*/
/*shell_sky_init();*/
shell_text_init();
/*shell_time_init();*/
/* shell_checkpoint_init();*/
shell_exec_init();
shell_base64_init();
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
test-deluge.c
#include "contiki.h"
#include "cfs/cfs.h"
#include "deluge.h"
#include "sys/node-id.h"
#include "loader/elfloader.h"
#include <stdio.h>
#include <string.h>
#ifndef SINK_ID
#define SINK_ID 1
#endif
#ifndef FILE_SIZE
#define FILE_SIZE 1000
#endif
PROCESS(deluge_test_process, "Deluge test process");
AUTOSTART_PROCESSES(&deluge_test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(deluge_test_process, ev, data)
{
static struct etimer et;
node_id_burn(2);
PROCESS_BEGIN();
if(node_id == SINK_ID) {
printf("Sink node: trying to transmit file.\n");
} else {
printf("Non-sink node: trying to recieve file.\n");
}
cfs_remove("hello-world.sky");
int fd = cfs_open("hello-world.sky", CFS_WRITE | CFS_READ);
if(fd < 0) {
process_exit(NULL);
}
#if 0
if(cfs_seek(fd, FILE_SIZE, CFS_SEEK_SET) != FILE_SIZE) {
printf("failed to seek to the end\n");
}
#endif
deluge_disseminate("hello-world.sky", node_id == SINK_ID);
cfs_close(fd);
etimer_set(&et, CLOCK_SECOND * 5);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
if(node_id != SINK_ID) {
fd = cfs_open("hello-world.sky", CFS_READ);
if(fd < 0) {
printf("failed to open the test file\n");
} else {
printf("Start dynamic loading\n");
int ret = elfloader_load(fd);
printf("%d\n", ret);
cfs_close(fd);
int i;
switch(ret) {
case ELFLOADER_OK:
for(i=0; elfloader_autostart_processes[i] != NULL; i++) {
printf("exec: starting process %s. \n",
elfloader_autostart_processes[i]->name);
}
autostart_start(elfloader_autostart_processes);
break;
default:
printf("Unkown return code from ELF loader (internal bug)\n");
break;
}
}
}
etimer_reset(&et);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
hello-world.c
#include "contiki.h"
#include <stdio.h> /* For printf() */
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
AUTOSTART_PROCESSES(&hello_world_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
printf("Hello, world\n");
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
So with great help from the contiki community I was able to gather the following solution:
"Hi,
The problem is that the build system of Contiki tries to "act smart"
and excludes symbols the application apparently does not need. So in
this case the deluge_disseminate function code is optimized away from
sky-shell-exec executable. Obviously, this conflicts with the basic
intuitions that the programmer has in case of over-the-air
programming.
To work around this issue, add a reference to deluge_disseminate in
sky-shell-exec code. For example, add this line (at global scope):
int (*keep)(void) = deluge_disseminate;
You can also try to tweak GCC linker options or use a custom linker script."
Using the same trick for node_id_burn as well, test-deluge.c runs.
The corrections have been made to the above code.
Hopefully this helps anyone else out there who may be struggling with OTA code in Contiki.

Simple multithreaded program segfault

Below is an attempt to write basic multi-threaded program where each thread will read one line from a log file (and does nothing). There is a bug somewhere and program segfaults (no core file generated).
If fgets() is replaced by fscanf() in readInput() then I see a core file. Backtrace is inconsistent and gives different call stack in different core file.
Contents of log file look like:
<num> hello<num>
all numbers less than 100
There are about 90 entries in the log file.
AFAIK, for what this code is doing, we don't need locks. But I put it for later use (and practice).
Can someone please point my mistakes in this code?
threads.h
---------
#include "../../include/global.h"
#include <pthread.h>
#define MAX_LOGS 101
#define NUM_THREADS 10
/* a single record in log file. Read by thread from input stream (file) */
typedef struct __thread_data {
int time; /* time stamp */
char log[32]; /* short log msg */
} thread_data_t;
/* heap (implemented by ordered array) storing the logs */
typedef struct __heap {
thread_data_t entry[MAX_LOGS];
int cur_size; /* used while inserting nodes? */
} heap_t;
add.c
-----
#include "../include/threads.h"
/* Stream from which logs are read (file stream here). Only one thread can
* read at a time */
FILE *fp;
pthread_mutex_t fp_lock;
/* thread start routine */
void *readInput(void *arg)
{
char log[40];
/* get lock for file read */
pthread_mutex_lock(&fp_lock);
/* Critical Section; read file */
if(!feof(fp)) {
fgets(log, 40, fp);
}
/* release lock */
pthread_mutex_unlock(&fp_lock);
pthread_exit(NULL);
}
int pthread_main()
{
int i, ret;
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&fp_lock, NULL);
fp = fopen("logs.txt", "r");
/* error check */
for(i=0; i<NUM_THREADS; i++) {
if(ret = pthread_create(&threads[i], NULL, readInput, NULL)) {
printf("Oops: %s\n", strerror(ret));
return EXIT_FAILURE;
}
}
for(i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
fclose(fp);
return EXIT_SUCCESS;
}
test.c
-------
#include "../include/threads.h"
int main()
{
return pthread_main();
}
Makefile
---------
CC = gcc
CFLAGS = -pthread
OBJFLAGS = -o
STDFLAGS = -std=c99
DBGS = -ggdb -pthread
OBJS = add.o test.o
HEADERS = include/threads.h
SOURCES = src/add.c src/test.c
all: $(OBJS)
$(CC) $(OBJFLAGS) th $(OBJS)
#make clean
$(OBJS): $(SOURCES) $(HEADERS)
$(CC) -c $(DBGS) $(SOURCES)
.PHONY: clean
clean:
rm -rf *.o
Backtrace of core dump.
#0 0x00007fff88d5b68e in pthread_create ()
(gdb) bt
#0 0x00007fff88d5b68e in pthread_create ()
#1 0x00000001051e0cf8 in pthread_main () at add.c:46
#2 0x00000001051e0dbf in main () at test.c:5
(gdb) list
1 #include "../include/threads.h"
2
3 int main()
4 {
5 pthread_main();
6 return 0;
7 }
(gdb) info thread
error on line 787 of "/SourceCache/gdb/gdb-1824/src/gdb/macosx/macosx-nat-infthread.c" in function "void print_thread_info(thread_t, int *)": (ipc/send) invalid destination port (0x10000003)
(gdb) info threads
5 0x00007fff88d47194 in thread_start ()
4 0x00007fff8a15e122 in __psynch_mutexwait ()
3 0x00007fff8a15e122 in __psynch_mutexwait ()
2 0x00007fff88dc242b in flockfile ()
* 1 0x00007fff88d5b68e in pthread_create ()
EDIT1: Thanks for all your feedback. I wanted to keep the actual code concise in original post. But here are the .c and .h files and also the Makefile I am using.
EDIT2: Adding backtrace of core. Line 46 in add.c is pthread_create() routine.
Problem lies in fopen. Code compiles, links and creates an executable correctly. When running it, it failed to open the log file as it could not locate it. I have below file/directory structure. Comment made by #self helped identify the issue.
src/
| Makefile
+--include/
| | threads.h
|
+--src/
| add.c
| test.c
| logs.txt
Either one of the following resolves the issue: (a) Changing the make rule to build executable in src directory and running it that directory. (b) Keep make rule as is but change fopen to point to src/logs.txt.

Resources