How can I make sure that the GNU linker ld is page aligning sections without a linker script? - ld

As the title suggests, I'm trying to compile and subsequently link a binary, and I want the sections (text, data, bss, etc.) to be paged-aligned. To achieve that, I'm trying to pass the --no-omagicoption to ld. The literal command I'm using (in my Makefile) is:
ld --no-omagic -o build/initlink.out $^
ld --help says the option should have the following effect:
--no-omagic Page align data, make text readonly
But if I do an nm -n on the output, the first symbol in each section is not aligned. For example:
$ nm -n build/initlink.out | grep ' [tT] ' | head -n 1
00000000004000f0 T main
$ nm -n build/initlink.out | grep ' [dD] ' | head -n 1
00000000006d74b0 d vsscanf.basefix
$ nm -n build/initlink.out | grep ' [bB] ' | head -n 1
00000000006e7200 B __bss_start
If it's important, one thing with which I'm trying to link is a static library (.a extension).
Is there anything that I could be doing wrong? Is there another way to ensure page alignment of sections, without resorting to a linker script? I've tried using the --section-alignment option, but when I do, I'm told that it's unrecognized. The static library defines some strange symbols (involving "linker sets," which I've found to be woefully undocumented) with which I was running into issues, so I want to try to do this without having to do anything but tell the linker to put sections in certain places.

Related

gcc command line structure arguments

I try to compile a c file with gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1).
I run the compiler in the source file's folder, but I keep getting the 'file not found' error message for the last argument ('bcm2835').
gcc -o gpio -l rt /home/pi/bcm2835-1.15/src/bcm2835.c -l bcm2835
/usr/bin/ld: cannot find -lbcm2835
collect2: error: ld returned 1 exit status
AFAIK, The gcc does not specify the third argument, I have no idea what this 3rd argument is used for and where to find it.
If I omit that argument, I get several error lines, each for one of the internal commands, like:
undefined reference to bcm2835_init
I also wish to know what the rt stands for. I could not find it in the official gcc docs.
Thanks
After -l, there should be no space. So it should be -lrt (not -l rt) and it should be -lbcm2835 (not -l bcm2835).
You need to add a linker search path with -L (uppercase L) right before calling -lbcm2835.
The input file should usually be last (that's the argument ending with main.c). That would be
gcc -o main -lrt -lbcm2835 /home/pi/bcm2835-1.15/main.c
-l links a library to the program. -L sets the library search path such that -l will find the libraries specified.
See this page for details on -l and -L.

LFS: GCC links wrong

I'm stuck on chapter 6.20 of the current LFS book. I get:
$ readelf -l a.out | grep Requesting
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
instead of the desired:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
The other tests lower down in the chapter all succeed.
This is my second time through the whole book being extremely careful and I got the same result last time around. Could there be some mistake?
For guidance it just said "The most likely reason is that something went wrong with the specs file adjustment.". That's a reference to 6.10 where it says "It is a good idea to visually inspect the specs file to verify the intended change was actually made" but there's no guidance as to what these intended changes are. But on this second go round I did check in /tools/lib/gcc/x86_64-pc-linux-gnu/7.2.0/specs that there was no mention of "tools" and the /usr paths were mentioned.
I seem to have solved it by making another specs file for the new compiler:
gcc -dumpspecs | sed -e 's#/tools##g' > `dirname $(gcc --print-libgcc-file-name)`/specs
After that, I redo the test:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
And all is well.

How to feed autocomplete data to a fish alias?

I am starting with fish and one of the things I could not find in the extensive documentation was autocomplete feeds.
There is mention of Tab Completions in the tutorial but it addresses existing the existence of the mechanism itself, not its configuration.
I have a bunch of virtual machines I connect to via
machinectl shell <name of machine> /bin/bash
I could make alises for all my machines via
function cm
machinectl $argv shell /bin/bash;
end
but this requires to remember and type the machine name.
How could I use the output of machinectl list | tail -n +2 | head -n -2 | cut -f1 -d' ' as a feed/hint to my cm command so that it shows them when using Tab?
EDIT: I somehow missed this right at the top of the documentation: Tab completion (I found it after reviewing the answers)
This should get you off to a good start:
complete --command cm --no-files \
--arguments '(machinectl list | tail -n +2 | head -n -2 | cut -f1 -d" ")'
Entering that at the command line will activate it for the current session; to make it permanent add the line to a completions file as Kurtis describes (~/.config/fish/completions/cm.fish).
See help complete. You'll find the completions that ship with fish, including completions for ssh, in $__fish_datadir/completions. A completion you write for a private function or command would be placed in ~/.config/fish/completions/$cmd_name.fish

Zenity --list --checklist issue

I'm trying to create a Zenity list to select kernel versions for removal.
So far I have:
dpkg -l | grep linux-image- | cut -f 3 -d ' ' | sed -e 's/^/FALSE /' | zenity --list --checklist --title="Select the Kernel versions to remove" --column="Kernel Version"
Most of this works in isolation, but I can't get the checkbox bits to work at all.
I just end up with a list of unchecked checkboxes and no corresponding items.
Finally figured it out, though I couldn't find it explained anywhere...
You need to specify a column name for all columns INCLUDING the checkbox column.
AND, there was no need to include the word FALSE at the start of every line as was implied by the Zenity help pages and examples I read.. strange.
So:
dpkg -l | grep linux-image- | cut -f 3 -d ' ' | zenity --list --checklist --title="Select the Kernel versions to remove" --column="Remove?" --column="Kernel Version"
works perfectly now (other than a GLib-WARNING... Bad file descriptor (9) on my system which is another issue).

How to ignore empty selections in XMLStarlet?

I have a script that performs many XML edit operations with XMLStarlet.
For instance, it removes all foo nodes if any are present:
xmlstarlet ed -d '//foo'
(except that in my script, the name of the element is not foo).
When no foo node is present, the following message is printed:
None of the XPaths matched; to match a node in the default namespace
use '_' as the prefix (see section 5.1 in the manual).
For instance, use /_:node instead of /node
But there is nothing wrong if no foo nodes are present in the input document.
So for this particular operation, I do want to avoid this particular warning,
while I do not want to disable such warnings in general.
How can I achieve this?
At the moment, deleting a node that does not exist is categorized by xmlstarlet as an error. The return code will be 1 which you will have to understand as "no nodes were removed".
The error message appears if you happen to use a document which has a default namespace:
No namespace:
echo '<foo />' | xmlstarlet sel -t -m foo -v joe
With a default namespace xmlstarlet prints the error message
echo '<foo xmlns="urn:foo" />' | xmlstarlet sel -t -m foo -v joe
None of the XPaths matched; to match a node in the default namespace
use '_' as the prefix (see section 5.1 in the manual).
For instance, use /_:node instead of /node
No default namespace:
echo '<ns:foo xmlns:ns="urn:foo" />' | xmlstarlet sel -t -m foo -v joe
In all of these cases, no nodes are found, and xmlstarlet thus exit with return code 1 (i.e. an error). The error message was to explain the error in the case where the user forgot that the document had a default namespace. I have discussed this with the author and more recently changes have been introduced to reduce the chances of these messages, and a way to inhibit them.
xmlstarlet has (yet undocumented) support for using the document's namespaces, without needing to declare them up-front:
Compare:
echo '<ns:foo xmlns:ns="urn:foo" />' | xmlstarlet sel -t -m ns:foo -v 'count(.)'
echo '<ns:foo xmlns:ns="urn:foo" />' | xmlstarlet sel -N xx=urn:foo -t -m xx:foo -v 'count(.)'
Technically, the commands are identical, except the first one depends on the document binding to the 'ns' prefix, while the second does not.
To inhibit the message, you have to redirecting stderr to null:
echo '<foo xmlns="urn:xxx"/>' |
xmlstarlet sel -t -m foo -v joe 2> /dev/null
The downside of this is that it suppresses legitimate error messages, not just this bogus one which is caused by the fact that the source document uses namespaces.
In recent builds --no-doc-namespace has been added to inhibit this behaviour
The change was introduced in this changeset and the changeset contains a long exchange regarding this error message, all caused by this StackOverflow question!