Strange behavior with pahole - linux-kernel

I am trying to use pahole to extract a struct (i.e., sock) from my freshly built kernel:
pahole sock ./vmlinux
But what I do not get the sock struct expected with the re-arranged members. I get a plain one as if it used a vmlinux from the distro I am running.
But when I extract all structs from it:
pahole vmlinux > pahole.out
And when I search for my re-arranged sock struct in the pahole.out file, I get the expected one -with the rearranged members.
Can someone tell me if I am doing something wrong?

Related

Entry point of Minix's processes

I'm studying Operating Systems and, of course, Minix 3.
Can someone tell me which file and line of code in Minix 3 are the entry points of:
Kernel;
Process Manager;
Memory Manager;
Virtual Memory Manager;
Any Device Driver.
Any of above will help me a lot.
Thanks.
I'm using the main github source:
https://github.com/Stichting-MINIX-Research-Foundation/minix
Try first searching for the device drivers since they are more "self-contained". Device drivers are found inhttps://github.com/Stichting-MINIX-Research-Foundation/minix/tree/master/minix/drivers
Instead of just pointing the entry points, I will show how I usually do. I will use the minix/drivers/video/fb/fb.h as an example. The fb is a driver responsible for controlling video displayed on a monitor. I could open any file, but I chose the fb.h since it is a header file and will contain the signatures of public functions.
I am on Linux so I can use the grep -r command. The -r flag search recursively for the given pattern. So by inspecting fb.h I found the following functions:
int arch_fb_init(int minor, struct edid_info *info);
int arch_get_device(int minor, struct device *dev);
int arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp);
int arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvs_copy);
int arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp);
int arch_pan_display(int minor, struct fb_var_screeninfo *fbvs_copy);
Well, arch_fb_init seems to be an entry point. To verify if arch_fb_init is indeed an entry point, I use
grep -r "arch_fb_init"
Which in turn returns the following
$ grep -r "arch_fb_init"
drivers/video/fb/arch/earm/fb_arch.c:arch_fb_init(int minor, struct edid_info *info)
drivers/video/fb/fb.h:int arch_fb_init(int minor, struct edid_info *info);
drivers/video/fb/fb.c: if (arch_fb_init(minor, infop) == OK) {
The second match is the fb.h itself. The other two are in fb_arch.c and fb.c. Then I go to those files and inspect each of them. Opening fb_arch.c and searching for arch_fb_init I find on line 315 an implementation of this function. By now, the implementation of the function could be more interesting because we want to figure out the caller/callee hierarchy.
Opening fb.c I find an occurrence of arch_fb_init on line 74, which is a call to arch_fb_init. This call to arch_fb_init is performed by another function named fb_open (line 60 on fb.c).
Now I repeat the process but now searching for fb_open. Performing another grep now returns the following.
$ grep -r "fb_open"
drivers/video/fb/fb.c:static int fb_open(devminor_t minor, int access, endpoint_t user_endpt);
drivers/video/fb/fb.c: .cdr_open = fb_open,
drivers/video/fb/fb.c:fb_open(devminor_t minor, int UNUSED(access), endpoint_t UNUSED(user_endpt))
All the occurrences are also in fb.c. By inspecting fb.c, one can see that the first grep match is a declaration of the fb_open function, and the third one is the implementation itself. The second one is using fb_open to construct a table (line 46 on file fb.c) that you can see below
/* Entry points to the fb driver. */
static struct chardriver fb_tab =
{
.cdr_open = fb_open,
.cdr_close = fb_close,
.cdr_read = fb_read,
.cdr_write = fb_write,
.cdr_ioctl = fb_ioctl
};
The commentary "Entry points to the fb driver." indicates that we are getting closer. If you have an IDE capable of parsing the Minix project, it will be easier to find all the callers/callee. If you don't have an IDE, you can use the grep command with the -r flag. If you know object orientation, this fb_tab is kind of a virtual table. Probably is setting callbacks that the kernel can use when calling this driver. I'm not sure because I never worked with minix before, but I have some general knowledge in OS, and the names used imply that I may be right.
Now searching for fb_tab by using grep, I get the following:
$ grep -r "fb_tab"
drivers/video/fb/fb.c:static struct chardriver fb_tab =
drivers/video/fb/fb.c: chardriver_task(&fb_tab);
All the occurrences once again in fb.c. The first match is the definition of fb_tab itself. The second one is the following
int
main(int argc, char *argv[])
{
env_setargs(argc, argv);
fb_edid_args_parse();
sef_local_startup();
chardriver_task(&fb_tab);
return OK;
}
By inspecting this main function, env_setargs and fb_edid_args_parse are probably just parsing arguments and setting flags. Now, the sef_local_startup and chardriver_task functions may be worth performing a grep.
Performing a grep on chardriver_task returns the following:
$ grep -r "chardriver_task"
drivers/examples/hello/hello.c: chardriver_task(&hello_tab);
drivers/sensors/tsl2550/tsl2550.c: chardriver_task(&tsl2550_tab);
drivers/sensors/bmp085/bmp085.c: chardriver_task(&bmp085_tab);
drivers/sensors/sht21/sht21.c: chardriver_task(&sht21_tab);
drivers/printer/printer/printer.c: chardriver_task(&printer_tab);
drivers/system/log/log.c: chardriver_task(&log_dtab);
drivers/system/random/main.c: chardriver_task(&r_dtab);
drivers/bus/i2c/i2c.c: chardriver_task(&i2c_tab);
drivers/bus/pci/main.c: chardriver_task(&driver);
drivers/video/fb/fb.c: chardriver_task(&fb_tab);
include/minix/chardriver.h:void chardriver_task(const struct chardriver *cdp);
servers/input/input.c: chardriver_task(&input_tab);
lib/libchardriver/chardriver.c: * chardriver_task *
lib/libchardriver/chardriver.c:void chardriver_task(const struct chardriver *cdp)
lib/libaudiodriver/audio_fw.c: chardriver_task(&audio_tab);
Many of the matches are calling the chardriver_task similar to the one found in fb.c but the following probably is the declaration
include/minix/chardriver.h:void chardriver_task(const struct chardriver *cdp);
And this one probably is the implementation
lib/libchardriver/chardriver.c:void chardriver_task(const struct chardriver *cdp)
As you can see, there isn't a clear entry point. It depends on what you're searching for. In the case of the fb driver, if you're searching for its initialization, it is probably the main function. However, if you're searching for how the kernel will be calling the driver probably is by the callbacks set on fb_tab.
If you can edit your question, someone will probably give you a better answer.

Unexplained behavior with pointers and protobufs

I'm struggling to figure out a reason for this behavior, or maybe this is suppose to happen and I just wasn't aware.
For background, I'm using proto3, and am doing this in Go1.15, and I do know that packed is the default in proto3, and I'm relatively new to protobufs.
I defined the following message in a proto file:
message Response {
repeated uint32 points = 1 [packed=true];
}
Which will generate the following code using protoc-gen-go v1.25.0.
type Response struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Points []uint32 `protobuf:"varint,3,rep,packed,name=points,json=points,proto3" json:"points,omitempty"`
}
I go to use the new struct, and it doesn't behave like I would normally expect a struct to behave. Here's some things I wrote, along with what was printed out.
newResponse := pb.Response{Points: []uint32{2,4,6,8}}
fmt.Println(newResponse)
//{{{} [] [] <nil>} 0 [] [2 4 6 8] --> I expect this
refToNewResponse := &newResponse
fmt.Println(refToNewResponse)
// points:2 points:4 points:6 points:8 --> not what I expected
Now you might be thinking, it's just formatting big deal.
But I expect a list... not numbers that each individually have a label. I've seen and used other protobufs... and when I see the response that they return, it doesn't look like this, it's one label to a list like:
points: [2 4 6 8]
I do need to use the reference version of this because I eventually want to expand and use a list of Responses which the generated code will spit out a slice of pointer Responses, but I can't understand why it's separating and labeling each element in the slice.
I'm hoping someone can point out something I'm doing or not doing that is causing this... thank you in advance.
This is indeed just formatting. Nothing has changed in the underlying data structure. You requested a repeated uint32 Points and it's literally printing them that way.
The marshaler in the protobuf implementation can really output whatever it likes, there is no reference version of the human-readable representation of a protobuf.
If you really must have a custom format for the .String() output, you can try a different proto library such as gogoprotobuf, or try various extensions. But ultimately, it's just human-readable output.
Note:
this has nothing to do with packed=true (which is indeed the default).
if you're confused about printing the pointer vs the basic type, it's because the String() method has a pointer receiver. See this question

Debugging Alpha BASIC for OpenVMS

I am trying to take over some projects involving DEC BASIC, A.K.A. VAX BASIC, A.K.A. Alpha BASIC. I am really hoping to run into someone with experience here. I have been through the user manual for VAX/Alpha BASIC through and though but I can't figure out how to debug shareable code.
I can create, compile and link shareable code, I can debug the code that references the shareable code, but I can't debug the shareable code. Any help would be greatly appreciated.
The commands I am using to compile and link are:
$ BASIC/DEBUG/NOOPTIMIZE COMPARE_DATES_TEST.BAS,COMPARE_DATES.BAS
$ LINK/SHAREABLE/DEBUG COMPARE_DATES.OBJ,COMPARE_DATES_SUB/OPT
$ LINK/DEBUG COMPARE_DATES_TEST,COMPARE_DATES_MAIN/OPT
$ RUN COMPARE_DATES_TEST
The contents of the two option files are:
$ type COMPARE_DATES_SUB.OPT
! COMPARE_DATES_SUB.OPT
SYMBOL_VECTOR=(COMPARE_DATES=PROCEDURE)
$ type COMPARE_DATES_MAIN.OPT
! COMPARE_DATES_MAIN.OPT
COMPARE_DATES/SHAREABLE
My shareable code has a bug, but I don't know where, the debugger reports:
— SRC: module COMPARE_DATES_TEST$MAIN -scroll-source————————————————————————————
1: EXTERNAL INTEGER FUNCTION COMPARE_DATES(STRING,STRING)
2: DECLARE STRING A$, B$
3: A$ = "01-APR-18"
4: B$ = "15-MAY-2017"
5:
-> 6: PRINT COMPARE_DATES(A$, B$)
7: END
— OUT -output———————————————————————————————————————————————————————————————————
stepped to COMPARE_DATES_TEST$MAIN\COMPARE_DATES_TEST$MAIN\%LINE 3
stepped to COMPARE_DATES_TEST$MAIN\COMPARE_DATES_TEST$MAIN\%LINE 4
stepped to COMPARE_DATES_TEST$MAIN\COMPARE_DATES_TEST$MAIN\%LINE 6
%BAS-F-SUBOUTRAN, Subscript out of range
-BAS-I-FROFUN, In external function COMPARE_DATES
-BAS-I-FROMOD, In module COMPARE_DATES_TEST
break on unhandled exception preceding 18446744071563830960
— PROMPT -error-program-prompt——————————————————————————————————————————————————
%DEBUG-I-SOURCESCOPE, source lines not available for %PC in scope number 0
Displaying source for 6\%PC
DBG>
Too long for a comment: You compiled with /NOOPTIMIZE, so I would have expected that a STEP/INTO when at line 6, PRINT COMPARE_DATES(A$, B$), would have stepped to COMPARE_DATES in your shareable image. I don't know why that's not the case, here. The debugger is right, you don't have the sources for DEC$BASRTL. Your shareable image is not installed, it is in your address space. It seems PRINT has problems with the passed argument. I would try a SET IMAGE COMPARE_DATES; SET MODULE/ALL; SET BREAK COMPARE_DATES at the initial debugger prompt. That makes all debug symbols of the shareable image known and sets a breakpoint in your function. And then a GO should get you into your function. (I noticed, that you have the same names for the function, the source module and the shareable image. This shouldn't be a problem.)

Using termios in Swift

Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)

What input section attributes are required to place a C variable in a data memory output section?

My application has a number of modules that each require some variables to be stored in off-chip non-volatile memory. To make the reading and writing of these easier, I'm trying to collect them together into a contiguous region of RAM, to that the NVM driver can address a single block of memory when communicating with the NVM device.
To achieve this, I have created a custom linker script containing the following section definition.
.nvm_fram :
{
/* Include the "nvm_header" input section first. */
*(.nvm_header)
/* Include all other input sections prefixed with "nvm_" from all modules. */
*(.nvm_*)
/* Allocate a 16 bit variable at the end of the section to hold the CRC. */
. = ALIGN(2);
_gld_NvmFramCrc = .;
LONG(0);
} > data
_GLD_NVM_FRAM_SIZE = SIZEOF(.nvm_fram);
The data region is defined in the MEMORY section using the standard definition provided by Microchip for the target device.
data (a!xr) : ORIGIN = 0x1000, LENGTH = 0xD000
One example of a C source file which attempts to place its variables in this section is the NVM driver itself. The driver saves a short header structure at teh beginning of the NVM section so that it can verify the content of the NVM device before loading it into RAM. No linker error reported for this variable.
// Locate the NVM configuration in the non-volatile RAM section.
nvm_header_t _nvmHeader __attribute__((section(".nvm_header")));
Another module that has variables to store in the .nvm_fram section is the communications (CANopen) stack. This saves the Module ID and bitrate in NVM.
// Locate LSS Slave configuration in the non-volatile RAM section.
LSS_slave_config_t _slaveConfig __attribute__((section(".nvm_canopen"))) =
{ .BitRate = DEFAULT_BITRATE, .ModuleId = DEFAULT_MODULEID };
Everything compiles nicely, but when the linker runs, the following error stops the build.
elf-ld.exe: Link Error: attributes for input section '.nvm_canopen' conflict with
output section '.nvm_fram'
It's important that the variables can be initialised with values by the crt startup, as shown by the _slaveConfig declaration above, in case the NVM driver cannot load them from the NVM device (it's blank, or the software version has changed, etc.). Is this what's causing the attributes mismatch?
There are several questions here and on the Microchip forums, which relate to accessing symbols that are defined in the linker script from C. Most of these concern values in the program Flash memory and how to access them from C; I know how to do this. There is a similar question, but this doesn't appear to address the attributes issue, and is a little confusing due to being specific to a linker for a different target processor.
I've read the Microchip linker manual and various GCC linker documents online, but can't find the relevant sections because I don't really understand what the error means and how it relates to my code. What are the 'input and output section attributes', where are they specified in my code, and how do I get them to match eachother?
The problem is due to the _nvmHeader variable not having an initial value assigned to it in the C source, but the _slaveConfig variable does.
This results in the linker deducing that the .nvm_fram output section is uninitialised (nbss) from the .nvm_header input section attributes. So, when it enconters initialised data in the .nvm_canopen input section from the _slaveConfig variable, there is a mismatch in the input section attributes: .nvm_fram is for uninitialised data, but .nvm_canopen contains initialised data.
The solution is to ensure that all variables that are to be placed in the .nvm_fram output section are given initial values in the C source.
// Type used to hold metadata for the content of the NVM.
typedef struct
{
void* NvmBase; // The original RAM address.
uint16_t NvmSize; // The original NVM section size.
} nvm_header_t;
// The linker supplies the gld_NVM_FRAM_SIZE symbol as a 'number'.
// This is represented as the address of an array of unspecified
// length, so that it cannot be implicitly dereferenced, and cast
// to the correct type when used.
extern char GLD_NVM_FRAM_SIZE[];
// The following defines are used to convert linker symbols into values that
// can be used to initialise the _nvmHeader structure below.
#define NVM_FRAM_BASE ((void*)&_nvmHeader)
#define NVM_FRAM_SIZE ((uint16_t)GLD_NVM_FRAM_SIZE)
// Locate the NVM configuration in the non-volatile RAM section.
nvm_header_t _nvmHeader __attribute__((section(".nvm_header"))) =
{
.NvmBase = NVM_FRAM_BASE, .NvmSize = NVM_FRAM_SIZE
};
The answer is therefore that the output section attributes may be determined partly by the memory region in which the section is to be located and also by the attributes of the first input section assigned to it. Initialised and uninitialised C variables have different input section attributes, and therefore cannot be located within the same output section.

Resources