How to debug kernel code without running kernel? - gcc

I'm reading some kernel books, I want to debug the spinlock_t usage, and prepared the following demo code:
////////////////////////////
// demo/spinlock.c
////////////////////////////
#include <linux/spinlock.h>
struct obj {
spinlock_t spinlock;
}
int demo0() {
struct obj o;
spin_lock_init(o.spinlock);
}
int main(){
demo0();
}
The Makefile seems like:
######################
# demo/Makefile
######################
demo: spinlock.c
gcc -o spinlock spinlock.c -I../linux-5.6.9/arch/x86/include -I../linux-5.6.9/include
The file tree seems like this
├── demo
└── linux-5.6.9
While meke, it gave me tones of errors (too many, I can't enumerate them here), It seems like that I missed some GCC CFLAGS or others.
How to debug kernel code line by line? Most of Google results are GDB/Qemu debugging within running kernel. Is there any suggestions to debug the kernel code without running the kernel?

Related

gcc -flto undefined reference errors

Recently I tried using link time optimization but didn't get very far. On the first attempt to link an exe I get a load of
{path}/bin/ld: <artificial>:(.text.startup+0x136): undefined reference to `some_function`
errors.
I can't see anything much special about the functions. We do take their addresses, and also refer to them via macros.
This is on RHEL 7.6 home rolled GCC 5.3 and binutils 2.34 (I don't know how they were configured unfortunately).
For a non-lto build I see that one of the functions is in a read-onlu section (according to nm). I see the same symbol in a .a file. From that I can find the .o file.
Going back to the lto version, with objdump -D I see
.gnu.lto_{missing function}.7c974f7d7bc920e2
And that's about as far as I can get. My only idea is that this is some sort of ODR violation that doesn't show up otherwise.
EDIT:
I've made some progress. Some if not all of the symbols are in .rodata arrays of pointers to functions.
These are generated in multiple files using some nasty C macros, something like this:
// file1.c
#include "param1_def.h"
#include "pfn_table.c"
// file2.c
#include "param2_def.h"
#include "pfn_table.c"
and
// pfn_table.c
function_type const MAKE_NAME(NAME, _functions) =
{
MAKE_NAME(NAME, _write_file),
MAKE_NAME(NAME, _read_file),
// etc
}
Where NAME is a macro defined in the paramX_def.h headers (and is different each time) and MAKE_NAME is a macro that pastes together the final names.

where is the interface header file of HIDL in AOSP?

I studied the HIDL using Nfc code in AOSP .
As i know, when INfc.hal is compiled, INfc.h is autogenerated like following picture.
In NxpService.cpp, there is code like following
#include <android/hardware/nfc/1.1/INfc.h>
But, I couldn't find that path.
where is the real path of android/hardware/nfc/1.1/INfc.h?
In addition, I became curious how gcc compile works in NxpService.cpp that uses INfc.h.
Could you explain how gcc compiler can find INfc.h and work without compile error?
INfc.hal
Path: /hardware/interfaces/nfc/1.1/INfc.hal
Android.bp
hidl_interface {
name: "android.hardware.nfc#1.1",
root: "android.hardware",
NxpService.cpp
Path: /hardware/nxp/nfc/1.1/NxpService.cpp
#include <android/hardware/nfc/1.1/INfc.h>
...
int main(){
sp<INfc> nfc_service = new Nfc();
status_t status = nfc_service->registerAsService();
android.hardware.nfc#1.1 would be at hardware/interfaces/nfc/1.1/ here.
The mappings for Android provided interfaces to their actual location are shown here https://source.android.com/devices/architecture/hidl/interfaces.
The files you look for are all auto-generated by hidl-gen, and they usually locate in out directory, e.g.
$ANDROID_ROOT/out/soong/.intermediates/hardware/interfaces/nfc/1.1/android.hardware.nfc#1.1_genc++_headers/gen/android/hardware/nfc/1.1

Cucumber-cpp step defiinition runner exits immediately

Based on the instructions given at cucumber-cpp github repo and cucumber-cpp step definition quick-start guide , I created my cucumber step definition files. The features and their step_definition files are under features/ folder, and the cpp code is built with cucumber-cpp headers and linked against libcucumber-cpp.a as instructed.
Cucumber step definition runners should stay running as a seperate process and cucumber command should execute while the runner is running. Indeed, the examples in the cucumber-cpp repository execute like that, but when I create my own step definitions, with gtest or boost test, they execute immediately, without waiting for calls from cucumber.
Onats-MacBook-Pro:bin onatbas$ ./tests/AdditionTest_TESTTARGET
Running main() from gtest_main.cc
[==========] Running 0 tests from 0 test cases.
[==========] 0 tests from 0 test cases ran. (0 ms total)
[ PASSED ] 0 tests.
Onats-MacBook-Pro:bin onatbas$
Instead of executing immediately, it should say nothing and wait for cucumber calls. I copy-pasted the example code from the cucumber-cpp into my project and they, too, exit immediately. So even though there's no source code difference between cucumber-cpp's examples and mine, they act differently.
I suspected the cmake build scripts might be linking with different libraries, but the linkage process is exactly the same too.
Does anybody have any idea on why this might be happening?
Here's the repository with minimum code that reproduces the error I have. https://github.com/onatbas/CucumberCppTest
The complete trace is at readme.
The cucumber files are under features/, and ther's only one feature that's identical to what's here
The runner executable is defined in tests/CMakeLists.txt
For quick reference: Here's the step-definition file
AdditionTest.cxx
#include <boost/test/unit_test.hpp>
#include <cucumber-cpp/defs.hpp>
#include <CucumberApp.hxx>
using cucumber::ScenarioScope;
struct CalcCtx {
Calculator calc;
double result;
};
GIVEN("^I have entered (\\d+) into the calculator$") {
REGEX_PARAM(double, n);
ScenarioScope<CalcCtx> context;
context->calc.push(n);
}
WHEN("^I press add") {
ScenarioScope<CalcCtx> context;
context->result = context->calc.add();
}
WHEN("^I press divide") {
ScenarioScope<CalcCtx> context;
context->result = context->calc.divide();
}
THEN("^the result should be (.*) on the screen$") {
REGEX_PARAM(double, expected);
ScenarioScope<CalcCtx> context;
BOOST_CHECK_EQUAL(expected, context->result);
}
and here's the tests/CMakeLists.txt file where the executable is added.
cmake_minimum_required(VERSION 3.1)
find_package(Threads)
set(CUCUMBERTEST_TEST_DEPENDENCIES cucumberTest
${CMAKE_THREAD_LIBS_INIT}
${GTEST_BOTH_LIBRARIES}
${GMOCK_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}
${CUCUMBER_BINARIES}
)
macro(ADD_NEW_CUCUMBER_TEST TEST_SOURCE FOLDER_NAME)
set (TARGET_NAME ${TEST_SOURCE}_TESTTARGET)
add_executable(${TARGET_NAME} ${CMAKE_SOURCE_DIR}/features/step_definitions/${TEST_SOURCE})
target_link_libraries(${TARGET_NAME} ${CUCUMBERTEST_TEST_DEPENDENCIES})
add_test(NAME ${TEST_SOURCE} COMMAND ${TARGET_NAME})
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER ${FOLDER_NAME})
endmacro()
ADD_NEW_CUCUMBER_TEST(AdditionTest "cucumberTest_tests")
Your example outputs
Running main() from gtest_main.cc
That main method will run the test runner's default behaviour instead of Cucumber-CPP's. The main mathod that you want (src/main.cpp) is included as part of the compiled cucumber-cpp library.
Try moving ${CUCUMBER_BINARIES} in CUCUMBERTEST_TEST_DEPENDENCIES before all others, or linking to testing libraries that do not contain a main method (e.g. GoogleTest ships with two libraries: one with and one without the main method).

Compiling a Vala source On Windows

I compiled a vala program by using following command:
valac test.vala
Of course am I able to run the program on my computer, but when I am trying to run the .exe file on a different one I get following error:
libglib-***.dll is missing on this computer
This is how my source code looks like:
using GLib;
int main(string[] args)
{
bool running = true;
while(running)
{
print("Hello World\n");
}
return 0;
}
The error is pretty clear, but what can I do against it? Thanks in advance.
Along your exe file you will need to install all the libraries you use (glib, gio, etc ...) and their own dependencies (Gtk will require gdk,cairo,pango, and some more).
Edit: take a look at this question on SO, the minimal dependencies are listed.

How to instrument gcc?

I have to instrument gcc for some purposes. The goal is to be able to track what GCC functions are called during a particularly compile. Unfortunately I'm not really familiar with the architecture of GCC so I need a little help. I tried the following steps:
1) Hacking gcc/Makefile.in and adding "-finstrument-functions" flag to T_CFLAGS.
2) I have an already implemented and tested version of start_test and end_test functions. They are called from gcc/main.c, before and after toplev_main() call. The containing file is linked to gcc (the object is added to OBJS-common and the dependency is defined later in gcc/Makefile.in)
3) Downloading prerequisites with contrib/download_prerequisites.
4) Executing the configuration from a clean build directory (on the same level with the source dir): ./../gcc-4.6.2/configure --prefix="/opt/gcc-4.6.2/" --enable-languages="c,c++"
5) Starting the build with "make all"
This way I runned out of memory, although I had 28G.
Next I tried to remove the T_CFLAGS settings from the Makefile and give -finstrument-functions to the make command: make CFLAGS="-finstrument-functions". The build was successful this way but when I tried to compile something it resulted empty output files. (Theoretically end_test should have written its result to a given file.)
What do I make wrong?
Thanks in advance!
Unless you specifically exclude it from being instrumented, main itself is subject to instrumentation, so placing calls to your start_test and end_test inside main is not how you want to do it. The 'correct' way to ensure that the file is opened and closed at the right times is to define a 'constructor' and 'destructor', and GCC automatically generates calls to them before and after main:
void start_test (void)
__attribute__ ( (no_instrument_function, constructor));
void end_test (void)
__attribute__ ( (no_instrument_function, destructor));
/* FILE to write profiling information. */
static FILE *profiler_out;
void start_test (void)
{
profiler_out = fopen ("profiler.out", "w");
if (profiler_out == NULL)
exit (-1);
}
void end_test (void)
{
fclose (profiler_out);
}
Footnotes:
Read more about constructor, destructor and no_instrument_function attributes here. They are function attributes that GCC understands.
Read this excellent guide to instrumentation, on the IBM website.

Resources