Firefox vs Chrome

Microsoft recently announced they were moving their Edge browser to the Chromium renderer. That makes me sad, not least for the risk of monoculture, but mostly because Google does not have my best interests at heart.

Google is an advertising company. They will not allow anything into Chromium that will have an adverse effect on advertising. To whit, anything that discourages human interaction will likely never make it into Chromium.

Eye catching is the name of the game in advertising. Any way to drag my attention to a particular point is the goal. We humans, having evolved as a potential prey animal, have a finely tuned visual system that will alert us to movement. “Oh, crap! Leopard in the leaves! Run!”

Case in point: animated gifs. Blinking, flashing, obnoxious animated gif have been the advertisement standard since Netscape banner ads debuted. Then came Flash. Now HTML5 has the <video> tag. My brain feels under assault.

Firefox has had the ability to disable animated gifs for years and years. There is still no built-in way to disable gif in Chrome. There are plug-ins that claim to halt/block animated gif, but I’ve never found one that actually works. The only solution to Chrome has been to globally block images and cherry pick sites to allow images (a whitelist). Firefox +1, Chrome -1.

Flashblock and other plugins would cure the scourge of Flash videos. Those plugins also made most of the web loading times tolerable. Chrome has “ask permission to run” for their built-in Flash player. Firefox +1, Chrome +1.

And now Flash is dying (buh bye) and HTML5 <video> is taking over. Video support is baked into the browser. Now the web is all about <video> advertising. Firefox to the rescue again. https://support.mozilla.org/en-US/questions/1238033  Seems to work so far. Firefox +1, Chrome -1.

Total score so far: Firefox 3, Chrome 1.  Long live Firefox.

Firefox about:config

image.animation_mode;none  <– disable animated gifs (has worked for years)

media.autoplay.default;1  <– stop auto play HTML video (works so far)

 

Fun with Python Regex

I’m a computer language nerd. I like programming languages. I’m in no way an expert. I do enjoy digging into new languages and even digging into the low level jiggery-pokery of languages I use day-to-day. Like C. But US$200 for the C standard language spec? Are you kidding me? No. Digging around on the committee website I found a draft: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

My first pass at the C enum parser is incredibly simple. I don’t want to write a full language parser because (a) that’s a lot of work and (b) it’s already been done before. I want something that would take a couple days tops to create and let me get back to fiddling with nl80211.

I’m using Python for the parser because I know Python pretty well. I’ve tinkered with the the C++ std::regex library as well but not for this project.

C comments can be either block comments surrounded by /*  */  or line comments starting with //.  For my toy parser, I’m handling comments very naively.

I’m mostly interested in the nl80211.h so I’m making some assumptions about the code format as I’m puttering with regex.

A C enum BNF-ish is (from the above pdf):

Screen Shot 2018-12-09 at 9.05.57 AM

I’m amusing myself with WordPress’ text formatting. I get distracted way too easily. (I dug further into the doc to find the definition of enumeration-constant.)

enum-specifier:

enum identifieropt { enumerator-list }
enum identifieropt { enumerator-list , }
enum identifier

enumerator-list:

enumerator
enumerator-list , enumerator

enumerator:

enumeration-constant
enumeration-constant = constant-expression

enumeration-constant:

identifier

Focus, Dave. Focus. HTML is just another language and it’s easy to get distracted. The break between LHS and RHS above is driving me nuts but I will move on. Focus!

A C identifier can be described by the Python regex “[a-zA-Z_][a-zA-Z_0-9]*”  Python regex whitespace is “\s” Required whitespace would be “\s+”. My first naive regex that searched for a starting enum: “enum\s+([a-zA-Z_][a-zA-Z_0-9]*)\s+{”  I’m assuming the enum+identifier+openbrace is on the same line.

The enumerator-list is another regex but more complicated because of the optional expression. I started with: “([a-zA-Z_][a-zA-Z_0-9]*)\s+,”  for a simple match. The constant-expression match would be “([a-zA-Z_][a-zA-Z_0-9]*)\s*=\s*([a-zA-Z_0-9]*)?,” and the copy paste started getting on my nerves.

I started fiddling with a Python printf-y .format() and a stumbled across a brain blast. Python f-strings are amazing when used with regex. Instead of trying to build a .format() or a %s block, I can assign my regex to a var. And I have a very readable regex. I can build up my regex piece by piece (for greater or for ill).

# C-style variable name
identifier = "[a-zA-Z_][a-zA-Z_0-9]*"

# using f strings to save myself some confusion 
open_brace = "\{"
close_brace = "\}"
whitespace = "\s+"
number = "-?[0-9]+"
operator = "(?P<operator>\+|-|<<)" # XXX subset of actual C operators

# I'm very sure this is not the proper use of the term 'atom'
# atom := number | identifier 
atom = f"(?:{identifier}|{number})"

# expression := atom
# := atom operator atom 
expression = f"({atom}({whitespace}{operator}{whitespace}{atom})?)"

# enum member regex
symbol_matcher = re.compile(f"(?P<identifier>{identifier})({whitespace}={whitespace}(?P<expression>{expression}))?")

# start of an emum declaration (XXX assumes open brace on same line as the
# 'enum' keywoard
enum_matcher = re.compile(f"enum{whitespace}({identifier}){whitespace}{open_brace}")

 

The f-string uses variables from Python’s context. So f”{identifier}{whitespace}{operator}{whitespace}” will expand to “[a-zA-Z_][a-zA-Z_0-9]*\s+(\+|-|<<)\s+” The f-string is much easier to read. The ?P<name> is a Python regex feature that stores the grouped regex expression into a key “name”.

s = "NL80211_NAN_FUNC_ATTR_MAX = NUM_NL80211_NAN_FUNC_ATTR - 1"
robj = symbol_matcher.search(s)
print(robj)
print(robj.groups())
print(robj.groupdict())

The code snippet gives me the following. Definitely need a lot of testing.

<_sre.SRE_Match object; span=(0, 57), match='NL80211_NAN_FUNC_ATTR_MAX = NUM_NL80211_NAN_FUNC_>
('NL80211_NAN_FUNC_ATTR_MAX', ' = NUM_NL80211_NAN_FUNC_ATTR - 1', 'NUM_NL80211_NAN_FUNC_ATTR - 1', 'NUM_NL80211_NAN_FUNC_ATTR - 1', ' - 1', '-')
{'identifier': 'NL80211_NAN_FUNC_ATTR_MAX', 'expression': 'NUM_NL80211_NAN_FUNC_ATTR - 1', 'operator': '-'}

Parsing C ‘enum’ with Python Regex.

In my previous post I mentioned I find C ‘enum’ a big annoying. An enum value captured in a network track or a packet hexdump is difficult to track backwards to a symbolic value. The nl80211.h header file uses enum extensively. As I continue to learn netlink and nl80211, I’d like a quick way to convert those enum into a human value.

Why not parse the header file and decode the enum? Python is my go-to for small string tasks.  (I mentioned I was parsing C enum in Python to a friend and he said, “That’s a very Dave move.” I’ll take it as a compliment, I suppose.)

C enum is straightforward: start counting as zero and auto increment. If there is an RHS expression, then that enum takes on that value and the auto increment continues from there.

enum nl80211_commands {
     /* don't change the order or add anything between, this is ABI! */
     NL80211_CMD_UNSPEC,

     NL80211_CMD_GET_WIPHY, /* can dump */
     NL80211_CMD_SET_WIPHY,
     NL80211_CMD_NEW_WIPHY,
     NL80211_CMD_DEL_WIPHY,
[snip]

(At some point I wonder if I should spring for the extra WordPress plugin for code formatting. Maybe.)

In the nl80211_commands above, NL80211_CMD_UNSPEC == 0, then NL80211_CMD_GET_WIPHY == 1. Simple counter. But danger lurks.

The RHS can be an expression. The expression can be a simple value.

enum nl80211_user_reg_hint_type {
        NL80211_USER_REG_HINT_USER      = 0,
        NL80211_USER_REG_HINT_CELL_BASE = 1,
        NL80211_USER_REG_HINT_INDOOR    = 2,
};

Or a complicated expression.

enum nl80211_tdls_peer_capability {
        NL80211_TDLS_PEER_HT = 1<<0,
        NL80211_TDLS_PEER_VHT = 1<<1,
        NL80211_TDLS_PEER_WMM = 1<<2,
};

The expression can reference previous values in the same enum as the next example. (Emphasis added.)

enum nl80211_sched_scan_plan {
        __NL80211_SCHED_SCAN_PLAN_INVALID,
        NL80211_SCHED_SCAN_PLAN_INTERVAL,
        NL80211_SCHED_SCAN_PLAN_ITERATIONS,

        /* keep last */
        __NL80211_SCHED_SCAN_PLAN_AFTER_LAST,
        NL80211_SCHED_SCAN_PLAN_MAX =
                __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1
};

Here’s my favorite example, showing the enum auto increment counter being reset. The example below adds new symbol identical to an existing symbol’s value and the auto increment continues on its merry way.

enum nl80211_commands {
[snip]
     NL80211_CMD_GET_BEACON,
     NL80211_CMD_SET_BEACON,
     NL80211_CMD_START_AP,
     NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP,
     NL80211_CMD_STOP_AP,
     NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP,
[snip]

I think it would be interesting to create a regex that can parse the enum. There are of course simpler ways to do this: I could just continue to use gdb. Most of the enums are small so not a big deal to manually count them. The large enum I could copy to a new file and manually count. But I like tinkering with regexes. And I’ve had this problem of decoding large enum for as long as I’ve used C (a long time). And it seems like a fun little project.

I’ve had co-workers do woodwork to relax. Several co-workers are mountain bikers (Boise is fantastic for mountain biking.) Video games are always a good way to relax. I like to tinker with small code projects.

C ‘enum’ is Annoying.

Writing a blog post is hard. “I’ll do it later,” I keep thinking. Maybe it’s like flossing–“I’ll do it later.” Next thing I know I’m spraying blood onto the ceiling while the hygienist tut-tuts about my bad habits. I floss (write) now and my future self will thank me.

I’m tinkering with nl80211, the successor to WEXT. WEXT is the Linux Wireless Extensions, a set of standardized ioctl for communicating userspace to the kernel level wireless drivers. WEXT is amazing but limited so the smart people got together and created a much more flexible system around NetLink.

As I’m tinkering with nl80211, I discover a frustrating extensive use of C enum. Using C enum in a network protocol is frustrating because with a large enum (say, greater than 10 elements), converting from an integer in a debug message back to the actual enum is well nigh impossible.

Case in point, the nl80211.h enum nl80211_attrs is ~400 lines and about 260 elements. In my little nl80211 baby-steps code, I fetch NL80211_CMD_GET_INTERFACE and get back an array filled with attribute + value.

        int i;
        for (i=0 ; i<NL80211_ATTR_MAX ; i++ ) {
                if (tb_msg[i]) {
                        printf("%d=%p type=%d len=%d\n", i, (void *)tb_msg[i], nla_type(tb_msg[i]), nla_len(tb_msg[i]));
                        hex_dump("msg", (unsigned char *)tb_msg[i], nla_len(tb_msg[i]));
                }
        }

Again this is baby steps code. I have no idea what I’m actually doing. I’m poking the box.

46=0x14db108 type=46 len=4
msg 0x00001080 08 00 2e 00 ....
206=0x14db110 type=206 len=1
msg 0x00001090 05 . 
217=0x14db120 type=217 len=4 
msg 0x000010a0 08 00 d9 00 ....
256=0x14db118 type=256 len=4
msg 0x000010b0 08 00 00 01 ....

Now I have a list of attributes coming back from the call. What the foo is 217? 256? A visit to gdb will give me answers!  The last element in the enum is NL80211_ATTR_PORT_AUTHORIZED so what is its value? First print the symbol, gives me the symbol. Print as hex (p/x) and as decimal (p/d) shows me the numerical value.

(gdb) p NL80211_ATTR_PORT_AUTHORIZED
$1 = NL80211_ATTR_PORT_AUTHORIZED
(gdb) p/x NL80211_ATTR_PORT_AUTHORIZED 
$2 = 0x103
(gdb) p/d NL80211_ATTR_PORT_AUTHORIZED 
$3 = 259

To find the symbol value of my integer, I can do the reverse in gdb. The typecast will convert an integer to the enum type.

(gdb) p (enum nl80211_attrs)46
$6 = NL80211_ATTR_GENERATION
(gdb) p (enum nl80211_attrs)206
$7 = NL80211_ATTR_MAX_CSA_COUNTERS
(gdb) p (enum nl80211_attrs)217
$8 = NL80211_ATTR_EXT_FEATURES
(gdb) p (enum nl80211_attrs)256
$9 = NL80211_ATTR_SCHED_SCAN_MAX_REQS

Having to dig into gdb for every enum in nl80211.h will be tiring. The problems grow in other header files that are nests of #ifdefs.

I me personally prefer using #define for symbols like this. The explicit link of a symbol to a value in source form is helpful.

 

autoreconf

I love GNU autoconf. I remember the days of downloading a .zip or a .tar.Z of source and having to manually edit a config.h, full of symbols I didn’t understand. GNU autoconf came along and now we just ./configure && make && make install.

Building Kismet from source, I had a difficulty with libusb which is not installed on my linux laptop. I hadn’t installed libusb because I hadn’t needed it yet. Building Kismet on another machine worked fine (libusb installed).

./configure
...
checking for libusb... no
configure: error: Package requirements (libusb-1.0) were not met:

Package 'libusb-1.0', required by 'virtual:world', not found

I was curious about Kismet’s modularity. OK, probably just need to check the configure flags. Usually a properly modular program would allow me to disable USB.

% ./configure --help...
 --disable-usb Disable libUSB support
...

However, “./configure -disable-usb” still gave me the libusb error. Puzzling. I finally noticed the ./configure was reporting an error, right after starting.

% ./configure --disable-usb
configure: WARNING: unrecognized options: --disable-usb
...

Debugging the generated configure script is a pain. Time to dust off my ancient autoconf knowledge. The configure script starts with the configure.ac. I opened that up and searched for the disable-usb;

AC_ARG_ENABLE(libusb,
  AS_HELP_STRING([--disable-usb], [Disable libUSB support]),

The help string is there. But why doesn’t it work? Is it something simple?

 AC_ARG_ENABLE(libusb,
- AS_HELP_STRING([--disable-usb], [Disable libUSB support]),
+ AS_HELP_STRING([--disable-libusb], [Disable libUSB support]),

It might be this simple. Now how do I rebuild the configure script from the configure.ac? It’s been a long time but I remember a magic ‘autoreconf’.

% sudo dnf install autoconf automake
% autoreconf

The autoreconf failed with a complaint about AC_PYTHON_MODULE macro. (I’ve lost the actual message to the mists of scrollback.) Autoconf is built around m4. A quick Google search for AC_PYTHON_MODULE leads to an m4 macro library: https://www.gnu.org/software/autoconf-archive/

Download the tarball, ./configure && make && make install and then try autoreconf again. Works! git diff shows the Kismet configure script updated. Run the configure again with –disable-libusb and no complaints.

 

Building Kismet under Fedora

I’m learning Kismet https://www.kismetwireless.com  I need a way to do remote wireless surveys. If I can send non-technical $customer a Magic Box that will send me a survey. WiFi problems are very environmental so having a second opinion of the environment will help me get my head around the issues.

I’m building Kismet from their git repo. The newer versions have a web interface that seems very enticing. With an internet connected device and a nice VPN overlay, I think I could get the remote information I need.

Kismet has instructions to build under Ubuntu. But for $reasons I’m running Fedora. I’ve been tinkering around with the list of required packages and I think I’ve hit the magic list:

sudo dnf install make automake gcc gcc-c++ kernel-devel git libmicrohttpd-devel pkg-config zlib-devel libnl3-devel libcap-devel libpcap-devel ncurses-devel NetworkManager-libnm-devel libdwarf libdwarf-devel elfutils-devel libsqlite3x-devel protobuf-devel protobuf-c-devel protobuf-compiler protobuf-c-compiler lm_sensors-devel libusb-devel fftw-devel

with some help from https://unix.stackexchange.com/questions/1338/what-is-the-fedora-equivalent-of-the-debian-build-essential-package

 

Continuing to Debug a OpenSSL Build

Continuing to tinker with the OpenSSL problems I’ve been having. Have a chunk of software whose building requires the older version of OpenSSL to be installed. But I want the newest OpenSSL dev package on my machine. We’re not going to get along.

I discovered I could selectively static link some of the libraries into the program. This was completely mind blowing feature to me. I started using the GCC linker way way back and was quite disconcerted by the -lfoo syntax which would find libfoo.a for linking.

In trying to force this software to build against a local copy of the older OpenSSL, I found problems with the final program trying to find the OpenSSL dynamic libraries. LD_LIBRARY_PATH would allow me to aim the software at my local lib but I was hoping there would be something simpler (that didn’t require setting that env var every time). Could I static link the executable? It’s been a while since I tried to static link a Linux app.

Quick google and found an even better answer:

https://stackoverflow.com/questions/6578484/telling-gcc-directly-to-link-a-library-statically

In the Makefile, I simply had to use -l:filename to link directly to a specific static library. With the -L flag, I could aim at a specific library location.

LDFLAGS += -lffi -lutil -lz -lm -lpthread -l:libssl.a -l:libcrypto.a -lrt -ldl

I had no idea this was possible with the linker. I’ve been using the GNU compilers for so many years and had no idea this was possible.

 

 

Debugging a Linux Hard Lockup

Building the linux-wireless-testing tree described in https://wireless.wiki.kernel.org/en/developers/documentation/git-guide   I have multiple MediaTek 7612 USB cards I’d like to get working. There’s exciting work going on in wireless to bring the MediaTek wifi into the mainline kernel.

I built the kernel on a Shuttle, loaded my new kernel. Plugged in the Alfa AWUS036ACM dongle, loaded up wpa_supplicant and my scripts. Desktop was unresponsive: hard lock up.

Power cycle. I’m on Fedora 28 which is systemd which uses journald. The journalctl -b -1 didn’t show any kernel panic.

Debugging a hard lock up of a kernel module seems easier than a kernel boot. The netconsole module https://www.kernel.org/doc/Documentation/networking/netconsole.txt will let me see the kernel log messages leading up to the lock-up.

I also need to investigate the watchdogs https://www.kernel.org/doc/Documentation/lockup-watchdogs.txt

Netconsole.

% sudo modprobe netconsole @/enp3s0,5566@172.19.10.254/

[69677.819810] netconsole: unknown parameter '@/enp3s0,5566@172' ignored
[69677.819903] console [netcon0] enabled
[69677.819904] netconsole: network logging started

OK, what did I screw up. Is there a way I can tickle the kernel into logging a message to test my config? Not from userspace, but Google search found the following useful post. (Oh, StackOverflow (and related) is there nothing you can’t do?)

https://serverfault.com/questions/140354/how-to-add-message-that-will-be-read-with-dmesg/140358#140358

Load/unload the module. Still not seeing any messages. Oh, right. I always forget this step. https://elinux.org/Debugging_by_printing#Netconsole_resources

echo 8 > /proc/sys/kernel/debug

Skipping over the “unknown parameter” problem for now and just setting the parameters manually. Here is what I have:

...trillian:coconut% cd /sys/kernel/config/netconsole/
...trillian:netconsole% ls
arthurdent/
...trillian:netconsole% cd arthurdent/
...trillian:arthurdent% ls
dev_name enabled extended local_ip local_mac local_port remote_ip remote_mac remote_port
...trillian:arthurdent% cat remote_mac
70:88:6b:81:ac:64
...trillian:arthurdent% cat remote_ip
172.16.17.181
...trillian:arthurdent% cat remote_port
5566
...trillian:arthurdent% cat local_ip
172.16.17.92
...trillian:arthurdent% cat local_port
6665
...trillian:arthurdent% cat dev_name
enp0s31f6

So now run netcat on arthurdent, my other machine.

nc -l -u 5566

Can test my netcat from trillian by sending a udp packet:

ls | nc -u 172.16.17.181 5566

And now time to turn the crank and watch the chaos unfold. Start up my wpa_supplicant and wpa_cli script and boom crash.

[ 546.841947] wlp0s20f0u1u2: authenticate with c4:b9:cd:dc:48:40
[ 547.140202] wlp0s20f0u1u2: send auth to c4:b9:cd:dc:48:40 (try 1/3)
[ 547.140226] BUG: unable to handle kernel NULL pointer dereference at 0000000000000011
[ 547.140228] PGD 800000083e025067 P4D 800000083e025067 PUD 83e072067 PMD 0
[ 547.140233] Oops: 0000 [#1] SMP PTI
[ 547.140236] CPU: 2 PID: 2503 Comm: wpa_supplicant Not tainted 4.19.0-rc2-wt #1
[ 547.140238] Hardware name: Shuttle Inc. SZ170/FZ170, BIOS 2.09 08/01/2017
[ 547.140258] RIP: 0010:ieee80211_wake_txqs+0x1e3/0x3d0 [mac80211]
[ 547.140261] Code: 4c 89 fe 4c 89 ef 48 8b 92 b0 02 00 00 e8 45 d6 2e f4 48 8b 3c 24 e8 0c bc 00 f4 48 83 c5 08 48 3b 6c 2
4 08 74 a0 4c 8b 7d 00 <41> 0f b6 57 11 3b 54 24 18 75 e6 4d 8d a7 28 ff ff ff f0 49 0f ba
[ 547.140263] RSP: 0018:ffff95038ea83ed0 EFLAGS: 00010293
[ 547.140265] RAX: ffff95038419e978 RBX: ffff95038419e000 RCX: ffff950384b18760
[ 547.140267] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff950384b18828
[ 547.140269] RBP: ffff95038419e970 R08: 00039e862fcdb16e R09: ffff95038a9b4230
[ 547.140271] R10: 0000000000000420 R11: ffffb8efc46c78d0 R12: ffff9503798251d0
[ 547.140273] R13: ffff950384b18760 R14: 0000000000000000 R15: 0000000000000000
[ 547.140275] FS: 00007f42ed60cdc0(0000) GS:ffff95038ea80000(0000) knlGS:0000000000000000
[ 547.140277] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 547.140279] CR2: 0000000000000011 CR3: 0000000835b30001 CR4: 00000000003606e0
[ 547.140281] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 547.140283] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 547.140284] Call Trace:

(Crash truncated here.)  Posted to the linux-wireless mailing list and am now getting some help.

 

The authenticity of host ‘X’ can’t be established.

The authenticity of host 'nn.nn.nn.nn (nn.nn.nn.nn)' can't be established.
ECDSA key fingerprint is SHA256:wls31bhGHFgGLYT403xsznbNS53Gzjlwrda5v7OUEZ4.
Are you sure you want to continue connecting (yes/no)?

Um. Wut?

This message always annoys me. I don’t like blindly accepting unknown connections.

From the root shell of my linode instance:

[root@lixxxx-xxx ssh]# ssh-keygen -l -f ssh_host_ecdsa_key
256 SHA256:wls31bhGHFgGLYT403xsznbNS53Gzjlwrda5v7OUEZ4 ssh_host_ecdsa_key.pub ()

Matches!

Now I’ll write this down so I can remember how to verify this next time.

 

Debugging an OpenSSL Version Problem.

I’m working in a system using an older version of OpenSSL. The system builds both a cross compiled version of Python and the same version of Python built for the host. Having the same version of python both in the embedded host and the local host allows me to run the Python scripts locally on the same exact same version of Python. I can test my Python scripts locally without having to push them to the remote firmware, which is slow and expensive.

Python uses OpenSSL. The embedded Python build used a local repo copy of the 1.0.x series OpenSSL. Consequently, the host Python build also needs to use the same older 1.0.x series OpenSSL. But the host Python build used the system (default) installed dev version of OpenSSL. I would have had to remove the current version of OpenSSL and install the older version. I was troubled by that requirement.

I built the OpenSSL 1.0.x, installed it to a $HOME tree. I then had to do the hard part of aiming the system’s host Python build at the older version. Seemed simple enough: find where CFLAGS and LDFLAGS was defined, change those to aim at my local OpenSSL.

CFLAGS+=$(HOME)/include/openssl

LDFLAGS+=$(HOME)/lib

But it wasn’t working. I knew it wasn’t working because the Python link would report not being able to find the newer OpenSSL symbol names so I knew the build was still using the newer version of header files.

I needed to debug my changes to the build. Along the way, I found some useful GCC options.

Debugging a header file include problem is straightforward: sabotage the build. I added “#error foo” to the host’s /usr/include/openssl/rsa.h and “#error bar” to the old openssl/rsa.h   Fun “make -B Modules/_ssl.o” and see which include file was being hit.  (The -B flag to make forces Make to rebuild the file regardless of timestamp.)  The build would fail with “error foo”. I was still getting the system header. I needed to see where GCC was finding its header files.

https://stackoverflow.com/questions/344317/where-does-gcc-look-for-c-and-c-header-files

specifically https://stackoverflow.com/a/41718748/39766

The set of paths where the compiler looks for the header files can be checked by the command:-

cpp -v

I added the ‘-v’ flag to the build, asking GCC to pass it along to the preprocessor.

gcc -Xpreprocessor -v $(CFLAGS) -c [etcetera]

Output looks like:

#include "..." search starts here:
#include <...> search starts here:
/home/dpoole/include/openssl
...
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.

Oops. First include should have been /home/dpoole/include not /home/dpoole/include/openssl   Fixed my CFLAGS and I’m now building Python against my local copy of openssl.

Python crashes on startup but progress!