What does the "MODULE_INFO(retpoline, "Y")" macro? - c

I see in some driver source code the line:
MODULE_INFO(retpoline, "Y")
What is does?

This macro defines key-value pairs that are stored in the compiled module files. You can use the modinfo command to display them. For example, when you compile this module, modinfo my_module.ko will include a line
retpoline: Y
You can find the definition of the macro and its documentation (such as it is) by searching on an LXR interface. It works by defining a symbol in the .modinfo section of the object file.
This mechanism is used for various metadata used by the module loaded in the kernel and by userland tools such as modprobe. Standard metadata include aliases, license, version, etc.
The retpoline tag indicates that the module is built with support for a mitigation against Spectre. I don't know why driver source code would declare this explicitly: as far as I understand, this should automatically be inserted (via a header) when compiling with retpoline support: this is a compiler feature, not a property of the source code.

Related

How can I get a protocol working under GNU-EFI?

I use GNU-EFI to develop UEFI apps. I have some trouble getting a protocol (EFI_SHELL_PROTOCOL) working under GNU-EFI. My compiler says that it is undefined. Should I include something? I already included efi.h and efilib.h. Do I need more?
Code that I tried:
EFI_SHELL_PROTOCOL shell;
The error that I got:
error: unknown type name ‘EFI_SHELL_PROTOCOL’; did you mean ‘EFI_OPEN_PROTOCOL’?
161 | EFI_SHELL_PROTOCOL shell;
The EFI_SHELL_PROTOCOL isn't part of the main UEFI interface, and is therefore not included in the main header files (e.g. efi.h) and not included in the main UEFI standard.
Instead, EFI_SHELL_PROTOCOL is just an optional extension (that may not exist, and I'd assume is only likely to exist when a shell is being used and provides it), with its own separate standard and its own separate header file.
Assuming you're using GNU's tools; the right files to include are probably efishellintf.h and efishellparm.h.
Currently, GNU-EFI does not support EFI_SHELL_PROTOCOL. It doesn't contain any related definitions about it.
If you want to use it with GNU-EFI, you can use this header file from edk2 (put it in inc folder, for example, inc/efishell.h). Then include this header file in inc/efi.h and add these lines:
lib/data.c:
EFI_GUID ShellProtocol = EFI_SHELL_PROTOCOL_GUID;
inc/efilib.h:
extern EFI_GUID ShellProtocol;
Rebuild your GNU-EFI and now you can use EFI_SHELL_PROTOCOL by locating it first.
EFI_SHELL_PROTOCOL *SP;
uefi_call_wrapper(BS->LocateProtocol, 3, &ShellProtocol, NULL, &SP);
The EFI_SHELL_PROTOCOL is fully documented in the UEFI Shell Specification (currently v2.2) which can be downloaded at https://uefi.org/specifications
GNU EFI does not currently implement EFI_SHELL_PROTOCOL or, indeed, all of the current UEFI Specification. For a reference implementation of the UEFI Shell Specification look at the EDK11 ShellPkg source code.

Importing Modules — customized Modules in C

I am currently learning the C programming language and I'm having some issues with importing modules I created.
I created a small module to read with fgets and flush the buffer from stdin perfectly and I don't want to keep writing the code every single time. I just want to import this small module like I used to do in Python. I didn't knew how because I'm not using an IDE. I'm just compiling with gcc in terminal and using a text editor. I tried to search with Google,but in vain.
You should create a header for your module that declares the functions in the module – and any other information that a consumer of the module needs. You might call that header weekly.h, a pun on your name, but you can choose any name you like within reason.
You should create a library (shared or static — that's up to you) that contains the functions (and any global variables, if you're so gauche as to have any) defined by your module. You might call it libweekly.so or libweekly.a — or using the extensions appropriate to your machine (.dylib and .a on macOS, for example). The source files might or might not be weekly.c — if there's more than one function, you'll probably have multiple source files, so they won't all be weekly.c. You should put this code (the header and the source files and their makefile) into a separate source directory.
You should install the header(s) and the library in a well-known location (e.g. $HOME/include for headers and $HOME/lib for the library — or maybe in the corresponding directories under /usr/local), and then ensure that the right options are used when compiling (-I$HOME/include for the headers) or linking (-L$HOME/lib and -lweekly).
Your source code using the module would contain:
#include "weekly.h"
and your code would be available. With shared libraries in $HOME/lib, you would have to ensure that the runtime system knows where to find the library. If you install it in /usr/local, that is done for you already. If you install it in $HOME/lib, you have to investigate things like /etc/ld.so.conf or the LD_LIBRARY_PATH or DYLIB_LIBRARY_PATH environment variables, etc.
You need to create a header file (.h) with your function declarations types and extern variables. Then in the program where you want to use those functions include this .h file and and add the compiled .o file (with your functions) to the object file list. And you are done.

How to find out functions missing from a library, but which are present in the exposed header file released along with the library?

We have a legacy library implementation and associated exposed header files. Recently we found that, some of the functions in the exposed header file, don't have corresponding definitions in the library implementation.
We want to check if there could be some more such functions. Is there any easier way of doing this rather than sifting through each and every API present in header and then checking if there is a definition for it?
You can generate C source from the header (Perl is a way to go!) that calls all the functions and try to compile it. Linker will complain about missing functions.
Try to create the ABI dump file by the abi-compliance-checker tool:
abi-compliance-checker -lib NAME -dump DESC.xml
DESC.xml file is the following:
<version>
1.0
</version>
<headers>
/path(s)/to/headers
</headers>
<libs>
/path(s)/to/libraries
</libs>
The resulting ABI dump file will contain the information you need about symbols declared in header files (SymbolInfo) and symbols exported by shared libraries (Symbols).
You can also generate ABI dump in the xml format by adding --xml option.
If this is C, you can do something like:
printf("", /* insert all functions here */);
That should pass them all as function pointers to printf. The ones that do not exist should show up as linker errors.
(In C++, you would have to list overloads explicitly, which makes it a bit more difficult.)
I'd be inclined to use ctags to generate a list of identifiers from the header file then use ar, emfar or elfdump in Unix or lib.exe or dumpbin.exe in Windows (see discussion here) to dump a list of identifiers from the library and then sort and diff the two lists.

How to resolve conflicting linker dependencies?

If I have two libraries, A.lib and B.lib, both of which export foo and bar, how do I tell the linker to use the symbol foo from A.lib and the symbol bar from B.lib?
You cannot. For your example you can have definitions from foo.lib or bar.lib but not both (especially if you cannot recompile the libraries and set symbol visibility so that only the symbols you want are exported). The order you link them against your application will depend on which library's definitions are used (you'll have to use the scientific method, I think the first one linked wins). Niklas Hansson's answer is a great way to do this dynamically but it seems you don't want to modify the original application, either, to dynamically pick/choose what symbols to take out of the libraries.
If you really wanted to you could mangle the symbol tables with a hex editor so that the symbols you don't want exported have different names (hacky, but it would work). I know on Linux there is a tool called objcopy that would let you do this (not sure about Windows).
You can use LIB.EXE /EXTRACT ... to extract only the object files you want to use, and link those files into your own application.
Or you may use LIB to create one new library containing the elements you need:
First, use /REMOVE on A.LIB to remove bar.obj:
LIB.EXE /OUT:ANOBAR.LIB /REMOVE:bar.obj A.LIB
Then combine A.LIB and B.LIB, and make sure to use ANOBAR.LIB as the last on the command line to ensure its foo.obj is used instead of B.LIB's:
LIB.EXE /OUT:COMBINED.LIB B.LIB ANOBAR.LIB
Details are found here: Managing a library, especially the paragraph:
You can use LIB [...] To replace a library member with a new object, specify the library containing the member object to be replaced and the file name for the new object (or the library that contains it). When an object that has the same name exists in more than one input file, LIB puts the last object specified in the LIB command into the output library. When you replace a library member, be sure to specify the new object or library after the library that contains the old object.
I didn't test the command lines given, but I've used similar ones extensively in the past.
If you are using dynamic libraries, you could use dynamic loading and pick foo from A and bar from B when loading.

How to use C static libraries in D?

I'm completely stumped on how to get FreeType 2.4.8 compiled as a static lib and usable from within my D application in Windows. I've tried running it over with objconv, coff2omf, and trying extern(C)/extern(System), etc. but nothing seems to work. I'm getting symbol not found errors, access violations and just a bunch of unhelpful errors.
How can I work around this? Am I correct in using pragma lib to link to my static libraries, and how do I reliably convert COFF static libs to OMF which DMD/Optlink can use?
EDIT: Some examples of what I've tried doing:
Compiling the FreeType source with VS 2010 as a static lib, linking in my D code with pragma lib. (Returned a "library format unknown" type error)
Same as above, but converting to OMF format using objconv and then trying to link with pragma lib. (Linked successfully, but still not able to call functions.)
Compiled a DLL of the FreeType source, ran it through implib to create an import library, tried linking with pragma lib. (Linked successfully, but unable to to call any functions due to "attempt to privileged function" or "access violation" errors)
I've tried defining function prototypes as all of: extern(System), extern(C), and extern(Windows). The first and third mangle the functions names of the extern-ed functions such that they don't match the static libraries, and the second compiles, but I get access violations during runtime when I actually try and call the functions.
I'm able to get it working via dynamic libraries and symbol loading, but I'd much prefer to not require a bunch of external dependencies when deploying my project.
I'm pretty sure Derelict2 has FreeType bindings: http://www.dsource.org/projects/derelict (See DerelictFT).
Yes, you will need extern(System) in your .d files with FT function declarations.
Static library a collection of object files. So no need for any kind of conversion (omf2coff, etc). DMD accepts a static libraries as arguments, so simple dmd file1.d file2.d C:/path/to/freetype.lib should work.
Edit:
I was wrong. Apparently I needed to read some documentation about the COFF2OMF.
Quote: The Microsoft COFF format apparently changed with Visual C++ 6.0. To use coff2omf on a .lib file with the newer format, use Microsoft's linker to convert the file to the earlier COFF format:
link /lib /convert freetype.lib
So, judging by the statement above you need to perform 2 steps.
First use the Microsoft's linker to convert static library you made with the VisualStudio (in COFF format) to the old COFF format as described above.
Now execute coff2omf freetype.lib to convert the static library into the OMF format.
It should now be ready to be used with the DMD the way described originally in my post.

Resources