Showing posts with label cli. Show all posts
Showing posts with label cli. Show all posts

Monday, April 19, 2010

To Have a CLI or Not?

Any embedded product for the telco market will eventually have a CLI. Most have Web GUIs but they are not good enough as scripting a JavaScript-heavy GUI is hell.

So customers usually demand a CLI so they can script their operations and perhaps make the configuration job easy -- any network admin worth his salt dislikes clicking a 1000 times to bring a system up to scratch.

Cīsco reigns king here. Everybody in the industry is familiar with their style of CLI and expects it. (The alternative is to give access to the native OS commands, i.e Linux, but this can be dangerous and does not make the configuration job easier.)

In a previous life I have seen this implemented ad-hoc in C (using ncurses) and in a different shop a horrendous mess made with Python (the latter was quasi-unmaintainable). Both had problems and did not conform to the Cīsco style.

Luckily a smart cookie published a LGPL libcli (written in C) which actually works well.

The only modification I had to make [and submit back] for adapting it to a serial port was to cut out some funny characters it was sending at the beginning of the session.

The downside was that I had to convince the powers that be in my company that this won't blow up their IP. Also I had to link in statically libsqlite3 so I can manipulate the password database which pushed the size of my custom CLI to 0.5 megabyte.

-ulianov

Monday, December 14, 2009

How to Learn What Code is Actually Disabling IRQs?

When one applies the PREEMPT_RT patch the spinlocks & mutexes get horribly overloaded. cli/sti use is frowned upon (x86) so one ends up with macros of macros of macros for locking so it is a head ache to see what functions are actually disbling interrupts.

Yet we are on x86 and the locking sequence generated by GCC is simple:
cli
...
sti
or could by a bit more complicated:
pushf
pop %reg
cli
...
push %reg
popf
Luckily I used objdump and a bit of massaging come to the rescue in the form of a neat script that finds all the object files that make up the compiled kernel and then searches the disassembler output for these sequences.

Bonus: the function names that do the locking are also printed.

Here comes findcli_x86.sh [run it at the root of the kernel tree after you compile the kernel]:
#!/bin/sh

# This file is licensed under GPLv2

# Note this works only with x86 code

obj_list='obj';
trap "rm -f $obj_list" 0 1 2 15

function extractcli()
{
file=$1;

[ ! -r "$file" ] && return 1;

[ -z "$OBJDUMP" ] && OBJDUMP=${CROSS_COMPILE}objdump

$OBJDUMP -dSCl $file | awk 'BEGIN {
idx="nosuchfunc"
}
/(^[a-zA-Z_]|cli[^a-z]|popf|sti[^a-z])/ && !/(file format|Disassembly)/ {
if($0 ~ /^[a-zA-Z_]/) {
idx=$1
} else {
F[idx]=(F[idx] "\n" "\t" $1 "\t" $NF);
}
}
END {
for(idx in F) {
print (" " idx F[idx])
}
}'
return 0
}

# main

find -type f -name '*.o' > $obj_list
for obj in $(cat $obj_list)
do
o=$(echo $obj | sed 's/^\.\///g')
[ "$o" = 'vmlinux.o' ] && continue; # this is the whole kernel
echo $o | grep -q 'built-in\.o' && continue; # these are aggregations

echo -en " \r$o" 1>&2
cnt=$(objdump -dS $o | grep -cw cli)
[ "$cnt" = '0' ] && continue;

echo -en " \r" 1>&2

src='???';
c=$(echo $o | sed 's/\.o$/\.c/g')
S=$(echo $o | sed 's/\.o$/\.S/g')
[ -f "$c" ] && src="$c"
[ -f "$S" ] && src="$S"

echo "$o: $cnt, src: $src"
extractcli $o
done
As usual awk comes to the rescue.

-ulianov

P.S. I looked for a decent decompiler for Linux other than objdump but I found only ancient ones and all broken. This is annoying as sometimes I need to see what external functions are called by an object file (.o).