#!/usr/bin/perl
use strict;
use warnings;
use 5.20.0;
use autodie;
my $LIBPQ = $ARGV[0];
die "usage: $0 /path/to/libpq\n" unless defined($ARGV[0]);
die "no libpq at $LIBPQ\n" unless -e $LIBPQ;
my $verbose = 0;
# Scan dynamic symbol list for desired symbols
open(my $syms, 'eu-nm --defined-only -D -f sysv -S ' . $LIBPQ . '|');
while(<$syms>) {
    chomp $_;
    if ($_ =~ /LIBPQ_VERSION_STR|LIBPQ_VERSION_NUM/) {
        # Find offset and length of symbol from ELF header
        my @v = split qr/[ \|\r\n]+/, $_;
        my ($symbol, $offset, $length) = ($v[0], eval("0x".$v[1]), eval("0x".$v[4]));
        printf STDERR "reading %s from %s offset %d length %d\n", $symbol, $LIBPQ, $offset, $length if $verbose;
        # Read symbol and length. This won't work for compressed ELF files but
        # we don't see those in the wild much. We could use eu-objdump or
        # eu-readelf to hexdump the compressed object, or just eu-elfcompress
        # to decompress it.
        open my $fh, "<", $LIBPQ;
        binmode $fh;
        seek $fh, $offset, 0;
        my $out;
        read $fh, $out, $length;
        chomp $out;
        close $fh;
        # String symbols are fine, we're done. Numeric symbols point to
        # host-endian data. Assume uint32.
        if ($symbol eq "LIBPQ_VERSION_NUM") {
            $out = unpack "I", $out;
        }
        say "$symbol=$out";
    }
}

