1*56726c7eSRobert Mustacchi#!/usr/bin/ksh 2*56726c7eSRobert Mustacchi# 3*56726c7eSRobert Mustacchi# 4*56726c7eSRobert Mustacchi# This file and its contents are supplied under the terms of the 5*56726c7eSRobert Mustacchi# Common Development and Distribution License ("CDDL"), version 1.0. 6*56726c7eSRobert Mustacchi# You may only use this file in accordance with the terms of version 7*56726c7eSRobert Mustacchi# 1.0 of the CDDL. 8*56726c7eSRobert Mustacchi# 9*56726c7eSRobert Mustacchi# A full copy of the text of the CDDL should have accompanied this 10*56726c7eSRobert Mustacchi# souroc. A copy of the CDDL is also available via the Internet at 11*56726c7eSRobert Mustacchi# http://www.illumos.org/liocnse/CDDL. 12*56726c7eSRobert Mustacchi# 13*56726c7eSRobert Mustacchi 14*56726c7eSRobert Mustacchi# 15*56726c7eSRobert Mustacchi# Copyright 2022 Oxide Computer Company 16*56726c7eSRobert Mustacchi# 17*56726c7eSRobert Mustacchi 18*56726c7eSRobert Mustacchi# 19*56726c7eSRobert Mustacchi# This test generates a binary with a lot of different symbol capabilities and 20*56726c7eSRobert Mustacchi# then selects different capability environments to try and ensure that the 21*56726c7eSRobert Mustacchi# rules for what we pick are honored. 22*56726c7eSRobert Mustacchi# 23*56726c7eSRobert Mustacchi 24*56726c7eSRobert Mustacchiexport LC_ALL=C.UTF-8 25*56726c7eSRobert Mustacchiunalias -a 26*56726c7eSRobert Mustacchiset -o pipefail 27*56726c7eSRobert Mustacchi 28*56726c7eSRobert Mustacchisc_arg0=$(basename $0) 29*56726c7eSRobert Mustacchisc_err=0 30*56726c7eSRobert Mustacchisc_tmpdir=/tmp/symcap.$$ 31*56726c7eSRobert Mustacchisc_prog="$sc_tmpdir/symcap" 32*56726c7eSRobert Mustacchi 33*56726c7eSRobert Mustacchi# 34*56726c7eSRobert Mustacchi# To build symbol caps, we need to annotate a .o file with object caps and then 35*56726c7eSRobert Mustacchi# turn that into a symbol cap with ld. The following arrays are used to create 36*56726c7eSRobert Mustacchi# this for us. sc_obj_hw1, sc_obj_hw2, and sc_obj_hw3 are the set of object 37*56726c7eSRobert Mustacchi# capabilities that we want to use and then eventually turn into symbol 38*56726c7eSRobert Mustacchi# capabilities. Each symbol capability prints out its own index when executed. 39*56726c7eSRobert Mustacchi# This means we can see which thing ld resolved to run based on the output. 40*56726c7eSRobert Mustacchi# The following summarizes our goals with each case: 41*56726c7eSRobert Mustacchi# 42*56726c7eSRobert Mustacchi# 0: none 43*56726c7eSRobert Mustacchi# 1: only hwcap 1 44*56726c7eSRobert Mustacchi# 2: only hwcap 1, but greater than (1) 45*56726c7eSRobert Mustacchi# 3: only hwcap 2 46*56726c7eSRobert Mustacchi# 4: only hwcap 2, but greater than (3) 47*56726c7eSRobert Mustacchi# 5: only hwcap 3 48*56726c7eSRobert Mustacchi# 6: only hwcap 3, but greater than (5) 49*56726c7eSRobert Mustacchi# 7: uses all 3 50*56726c7eSRobert Mustacchi# 8: differs from (7) in hwcap1 51*56726c7eSRobert Mustacchi# 52*56726c7eSRobert Mustacchisc_obj_hw1=( "0x0" "0x5" "0x42" "0x0" "0x0" "0x0" "0x0" 53*56726c7eSRobert Mustacchi "0x3" "0x8" ) 54*56726c7eSRobert Mustacchisc_obj_hw2=( "0x0" "0x0" "0x0" "0x23" "0xff00" "0x0" "0x0" 55*56726c7eSRobert Mustacchi "0xff7ff6" "0xff7ff6" ) 56*56726c7eSRobert Mustacchisc_obj_hw3=( "0x0" "0x0" "0x0" "0x0" "0x0" "0x12345" "0x7000000" 57*56726c7eSRobert Mustacchi "0x87654321" "0x87654321" ) 58*56726c7eSRobert Mustacchi 59*56726c7eSRobert Mustacchipass() 60*56726c7eSRobert Mustacchi{ 61*56726c7eSRobert Mustacchi typeset msg="$*" 62*56726c7eSRobert Mustacchi echo "TEST PASSED: $msg" 63*56726c7eSRobert Mustacchi} 64*56726c7eSRobert Mustacchi 65*56726c7eSRobert Mustacchiwarn() 66*56726c7eSRobert Mustacchi{ 67*56726c7eSRobert Mustacchi typeset msg="$*" 68*56726c7eSRobert Mustacchi [[ -z "$msg" ]] && msg="failed" 69*56726c7eSRobert Mustacchi echo "TEST FAILED: $msg" >&2 70*56726c7eSRobert Mustacchi sc_err=1 71*56726c7eSRobert Mustacchi} 72*56726c7eSRobert Mustacchi 73*56726c7eSRobert Mustacchifatal() 74*56726c7eSRobert Mustacchi{ 75*56726c7eSRobert Mustacchi typeset msg="$*" 76*56726c7eSRobert Mustacchi [[ -z "$msg" ]] && msg="failed" 77*56726c7eSRobert Mustacchi echo "$sc_arg0: $msg" >&2 78*56726c7eSRobert Mustacchi exit 1 79*56726c7eSRobert Mustacchi} 80*56726c7eSRobert Mustacchi 81*56726c7eSRobert Mustacchicleanup() 82*56726c7eSRobert Mustacchi{ 83*56726c7eSRobert Mustacchi rm -rf "$sc_tmpdir" 84*56726c7eSRobert Mustacchi} 85*56726c7eSRobert Mustacchi 86*56726c7eSRobert Mustacchisanity_check() 87*56726c7eSRobert Mustacchi{ 88*56726c7eSRobert Mustacchi if (( ${#sc_obj_hw1[@]} != ${#sc_obj_hw2[@]} )); then 89*56726c7eSRobert Mustacchi fatal "sc_obj_hw1 does not match length of sc_obj_hw2" 90*56726c7eSRobert Mustacchi fi 91*56726c7eSRobert Mustacchi 92*56726c7eSRobert Mustacchi if (( ${#sc_obj_hw2[@]} != ${#sc_obj_hw3[@]} )); then 93*56726c7eSRobert Mustacchi fatal "sc_obj_hw1 does not match length of sc_obj_hw2" 94*56726c7eSRobert Mustacchi fi 95*56726c7eSRobert Mustacchi} 96*56726c7eSRobert Mustacchi 97*56726c7eSRobert Mustacchisetup() 98*56726c7eSRobert Mustacchi{ 99*56726c7eSRobert Mustacchi typeset tolink= 100*56726c7eSRobert Mustacchi 101*56726c7eSRobert Mustacchi if ! mkdir "$sc_tmpdir"; then 102*56726c7eSRobert Mustacchi fatal "failed to make directory $sc_tmpdir" 103*56726c7eSRobert Mustacchi fi 104*56726c7eSRobert Mustacchi 105*56726c7eSRobert Mustacchi trap 'cleanup' EXIT 106*56726c7eSRobert Mustacchi 107*56726c7eSRobert Mustacchi cat > $sc_tmpdir/main.c <<EOF 108*56726c7eSRobert Mustacchiextern void symcap_print(void); 109*56726c7eSRobert Mustacchi 110*56726c7eSRobert Mustacchiint 111*56726c7eSRobert Mustacchimain(void) 112*56726c7eSRobert Mustacchi{ 113*56726c7eSRobert Mustacchi symcap_print(); 114*56726c7eSRobert Mustacchi return (0); 115*56726c7eSRobert Mustacchi} 116*56726c7eSRobert MustacchiEOF 117*56726c7eSRobert Mustacchi if (( $? != 0 )); then 118*56726c7eSRobert Mustacchi fatal "failed to write main.c" 119*56726c7eSRobert Mustacchi fi 120*56726c7eSRobert Mustacchi 121*56726c7eSRobert Mustacchi tolink="$sc_tmpdir/main.c" 122*56726c7eSRobert Mustacchi 123*56726c7eSRobert Mustacchi for (( i = 0; i < ${#sc_obj_hw1[@]}; i++)); do 124*56726c7eSRobert Mustacchi typeset in="$sc_tmpdir/$i.c" 125*56726c7eSRobert Mustacchi typeset map="$sc_tmpdir/$i.map" 126*56726c7eSRobert Mustacchi typeset ofile="$sc_tmpdir/$i.o" 127*56726c7eSRobert Mustacchi typeset obj="$sc_tmpdir/$i.o.obj" 128*56726c7eSRobert Mustacchi typeset sym="$sc_tmpdir/$i.o.sym" 129*56726c7eSRobert Mustacchi 130*56726c7eSRobert Mustacchi cat > $in <<EOF 131*56726c7eSRobert Mustacchi#include <stdio.h> 132*56726c7eSRobert Mustacchi 133*56726c7eSRobert Mustacchivoid 134*56726c7eSRobert Mustacchisymcap_print(void) 135*56726c7eSRobert Mustacchi{ 136*56726c7eSRobert Mustacchi printf("%u\n", $i); 137*56726c7eSRobert Mustacchi} 138*56726c7eSRobert MustacchiEOF 139*56726c7eSRobert Mustacchi if (( $? != 0 )); then 140*56726c7eSRobert Mustacchi fatal "failed to write $in" 141*56726c7eSRobert Mustacchi fi 142*56726c7eSRobert Mustacchi 143*56726c7eSRobert Mustacchi cat > $map <<EOF 144*56726c7eSRobert Mustacchi\$mapfile_version 2 145*56726c7eSRobert MustacchiCAPABILITY { 146*56726c7eSRobert Mustacchi HW_1 += ${sc_obj_hw1[$i]}; 147*56726c7eSRobert Mustacchi HW_2 += ${sc_obj_hw2[$i]}; 148*56726c7eSRobert Mustacchi HW_3 += ${sc_obj_hw3[$i]}; 149*56726c7eSRobert Mustacchi}; 150*56726c7eSRobert MustacchiEOF 151*56726c7eSRobert Mustacchi if (( $? != 0 )); then 152*56726c7eSRobert Mustacchi fatal "failed to write $map" 153*56726c7eSRobert Mustacchi fi 154*56726c7eSRobert Mustacchi 155*56726c7eSRobert Mustacchi # 156*56726c7eSRobert Mustacchi # There are three steps to creating a symbol capability due to 157*56726c7eSRobert Mustacchi # the world we're in. First we need to make the normal .o. Then 158*56726c7eSRobert Mustacchi # we use a mapfile to add the object caps, while reducing 159*56726c7eSRobert Mustacchi # visibility. Then we turn the object cap into a symbol cap. 160*56726c7eSRobert Mustacchi # 161*56726c7eSRobert Mustacchi if ! gcc -m64 -o $ofile -c $in; then 162*56726c7eSRobert Mustacchi fatal "failed to create object file $ofile" 163*56726c7eSRobert Mustacchi fi 164*56726c7eSRobert Mustacchi 165*56726c7eSRobert Mustacchi # 166*56726c7eSRobert Mustacchi # If the entry has a zero for all cases (e.g. our default case), 167*56726c7eSRobert Mustacchi # then skip the rest of this processing and append the .o. 168*56726c7eSRobert Mustacchi # 169*56726c7eSRobert Mustacchi if (( sc_obj_hw1[i] == 0 && sc_obj_hw2[i] == 0 && 170*56726c7eSRobert Mustacchi sc_obj_hw3[i] == 0 )); then 171*56726c7eSRobert Mustacchi tolink="$tolink $ofile" 172*56726c7eSRobert Mustacchi continue 173*56726c7eSRobert Mustacchi fi 174*56726c7eSRobert Mustacchi 175*56726c7eSRobert Mustacchi if ! ld -r -o $obj $ofile -M$map -Breduce; then 176*56726c7eSRobert Mustacchi fatal "failed to create object cap file $obj" 177*56726c7eSRobert Mustacchi fi 178*56726c7eSRobert Mustacchi 179*56726c7eSRobert Mustacchi if ! ld -r -o $sym -z symbolcap $obj; then 180*56726c7eSRobert Mustacchi fatal "failed to create symbol cap file $sym" 181*56726c7eSRobert Mustacchi fi 182*56726c7eSRobert Mustacchi 183*56726c7eSRobert Mustacchi tolink="$tolink $sym" 184*56726c7eSRobert Mustacchi done 185*56726c7eSRobert Mustacchi 186*56726c7eSRobert Mustacchi if ! gcc -m64 -o $sc_prog $tolink; then 187*56726c7eSRobert Mustacchi fatal "failed to create $sc_prog" 188*56726c7eSRobert Mustacchi fi 189*56726c7eSRobert Mustacchi} 190*56726c7eSRobert Mustacchi 191*56726c7eSRobert Mustacchi# 192*56726c7eSRobert Mustacchi# Given a set of caps, indicate which index we expect to be printed out and 193*56726c7eSRobert Mustacchi# check for that. 194*56726c7eSRobert Mustacchi# 195*56726c7eSRobert Mustacchirun_one() 196*56726c7eSRobert Mustacchi{ 197*56726c7eSRobert Mustacchi typeset index="$1" 198*56726c7eSRobert Mustacchi typeset caps="$2" 199*56726c7eSRobert Mustacchi typeset out= 200*56726c7eSRobert Mustacchi 201*56726c7eSRobert Mustacchi out=$(LD_CAP_FILES=$sc_prog LD_HWCAP="$caps" $sc_prog) 202*56726c7eSRobert Mustacchi if (( $? != 0 )); then 203*56726c7eSRobert Mustacchi warn "failed to execute $sc_prog with cap $caps" 204*56726c7eSRobert Mustacchi return 205*56726c7eSRobert Mustacchi fi 206*56726c7eSRobert Mustacchi 207*56726c7eSRobert Mustacchi if [[ "$out" != "$index" ]]; then 208*56726c7eSRobert Mustacchi warn "$caps had wrong output, found $out, expected $index" 209*56726c7eSRobert Mustacchi else 210*56726c7eSRobert Mustacchi pass "LD_HWCAP=$caps" 211*56726c7eSRobert Mustacchi fi 212*56726c7eSRobert Mustacchi} 213*56726c7eSRobert Mustacchi 214*56726c7eSRobert Mustacchisanity_check 215*56726c7eSRobert Mustacchisetup 216*56726c7eSRobert Mustacchi 217*56726c7eSRobert Mustacchi# 218*56726c7eSRobert Mustacchi# First, go through and verify that if we match the caps exactly for this, we'll 219*56726c7eSRobert Mustacchi# choose this symbol. 220*56726c7eSRobert Mustacchi# 221*56726c7eSRobert Mustacchirun_one 0 "[1]0x0,[2]0x0,[3]0x0" 222*56726c7eSRobert Mustacchirun_one 1 "[1]0x5,[2]0x0,[3]0x0" 223*56726c7eSRobert Mustacchirun_one 2 "[1]0x42,[2]0x0,[3]0x0" 224*56726c7eSRobert Mustacchirun_one 3 "[1]0x0,[2]0x23,[3]0x0" 225*56726c7eSRobert Mustacchirun_one 4 "[1]0x0,[2]0xff00,[3]0x0" 226*56726c7eSRobert Mustacchirun_one 5 "[1]0x0,[2]0x0,[3]0x12345" 227*56726c7eSRobert Mustacchirun_one 6 "[1]0x0,[2]0x0,[3]0x7000000" 228*56726c7eSRobert Mustacchirun_one 7 "[1]0x3,[2]0xff7ff6,[3]0x87654321" 229*56726c7eSRobert Mustacchirun_one 8 "[1]0x8,[2]0xff7ff6,[3]0x87654321" 230*56726c7eSRobert Mustacchi 231*56726c7eSRobert Mustacchi# 232*56726c7eSRobert Mustacchi# For cases where we have multiple symbol caps at a given level, show that we 233*56726c7eSRobert Mustacchi# pick a sub one when we're between the two. 234*56726c7eSRobert Mustacchi# 235*56726c7eSRobert Mustacchirun_one 0 "[1]0x40,[2]0x0,[3]0x0" 236*56726c7eSRobert Mustacchirun_one 1 "[1]0x45,[2]0x0,[3]0x0" 237*56726c7eSRobert Mustacchirun_one 1 "[1]0x45,[2]0x10,[3]0x0" 238*56726c7eSRobert Mustacchirun_one 2 "[1]0x142,[2]0x10,[3]0x0" 239*56726c7eSRobert Mustacchirun_one 3 "[1]0x1,[2]0x137,[3]0x0" 240*56726c7eSRobert Mustacchi 241*56726c7eSRobert Mustacchi# 242*56726c7eSRobert Mustacchi# We expect the system to pick the "best" aka highest capability. So for the 243*56726c7eSRobert Mustacchi# next round we attempt to combine multiple values and see which we pick. In 244*56726c7eSRobert Mustacchi# particular here we're trying to pick between things at the same level and also 245*56726c7eSRobert Mustacchi# ensure we pick the one that is higher (e.g. hw3 > hw2 > hw1) 246*56726c7eSRobert Mustacchi# 247*56726c7eSRobert Mustacchirun_one 6 "[1]0x47,[2]0xff23,[3]0x7012345" 248*56726c7eSRobert Mustacchirun_one 5 "[1]0x47,[2]0xff23,[3]0x6012345" 249*56726c7eSRobert Mustacchirun_one 5 "[1]0x47,[2]0xff23,[3]0x1012345" 250*56726c7eSRobert Mustacchirun_one 4 "[1]0x47,[2]0xff23,[3]0x1002345" 251*56726c7eSRobert Mustacchirun_one 3 "[1]0x47,[2]0x7723,[3]0x1002345" 252*56726c7eSRobert Mustacchirun_one 3 "[1]0x47,[2]0x0f23,[3]0x1002345" 253*56726c7eSRobert Mustacchirun_one 3 "[1]0x47,[2]0x0023,[3]0x1002345" 254*56726c7eSRobert Mustacchirun_one 2 "[1]0x47,[2]0x0003,[3]0x1002345" 255*56726c7eSRobert Mustacchirun_one 2 "[1]0x46,[2]0x0003,[3]0x1002345" 256*56726c7eSRobert Mustacchirun_one 1 "[1]0x35,[2]0x0003,[3]0x1002345" 257*56726c7eSRobert Mustacchirun_one 1 "[1]0x15,[2]0x0003,[3]0x1002345" 258*56726c7eSRobert Mustacchirun_one 0 "[1]0x10,[2]0x0003,[3]0x1002345" 259*56726c7eSRobert Mustacchi 260*56726c7eSRobert Mustacchi# 261*56726c7eSRobert Mustacchi# Finally we want a few tests that verify that when things match, the lowest bit 262*56726c7eSRobert Mustacchi# of it decides. 263*56726c7eSRobert Mustacchi# 264*56726c7eSRobert Mustacchirun_one 8 "[1]0xb,[2]0xff7ff6,[3]0x87654321" 265*56726c7eSRobert Mustacchirun_one 8 "[1]0x3b,[2]0xff7ff6,[3]0x87654321" 266*56726c7eSRobert Mustacchirun_one 8 "[1]0xffffffff,[2]0xffffffff,[3]0xffffffff" 267*56726c7eSRobert Mustacchirun_one 7 "[1]0xfffffff7,[2]0xffffffff,[3]0xffffffff" 268*56726c7eSRobert Mustacchi 269*56726c7eSRobert Mustacchiexit $sc_err 270