mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-13 21:39:57 +08:00
Implement portable kernel symbol namespace tool
- The script's use of sort proved to not be portable - No need to check the commits as symbols are only added - Regenerated kernel header to reset the sort order Update #4475
This commit is contained in:
parent
f5c405ec05
commit
59f652fe88
@ -121,6 +121,82 @@ $ git log freebsd-org
|
||||
```
|
||||
to figure out the current FreeBSD baseline.
|
||||
|
||||
Updates to FreeBSD or RTEMS Kernel Support
|
||||
------------------------------------------
|
||||
|
||||
If you update code or change any defines that effect the generated
|
||||
code in the following paths:
|
||||
|
||||
* `freebsd/sys/*.[ch]`
|
||||
* `rtemsbsd/rtems/rtems-kernel-*.c`
|
||||
|
||||
you need to see if any new kernel symbols have been generated or
|
||||
exposed. The tool `rtems-kern-symbols` command supports checking and
|
||||
updating the kernel symbol namespace.
|
||||
|
||||
The public (global) kernel symbosl need to reside in a private
|
||||
namespace to avoid clashing with symbols in the user space code or
|
||||
applications. The FreeBSD kernel names functions and variables
|
||||
assuming a private kernel only symbols space. RTEMS builds FreeBSD
|
||||
kernel and user space code in the same symbols space so there can be
|
||||
clashes. We manage this by maintaining a header file that maps the
|
||||
global kernel symbols to a private namespace. For example `malloc` is
|
||||
mapped to `_bsd_malloc`.
|
||||
|
||||
The set of symbols to map is not easy to obtain because symbols may be
|
||||
the result of complex preprocessing of the source, the code is
|
||||
specific to a BSP or the code is controlled by a buildset.
|
||||
|
||||
The approach we use is to not remove symbols unless you are certain
|
||||
the symbols have been removed from the FreeBSD kernel source. This is
|
||||
a manual operation.
|
||||
|
||||
You are required to check symbols with a 32bit and 64bit
|
||||
architecture.
|
||||
|
||||
If you are working on a specific BSP and related drivers please make
|
||||
sure the kernel symbols are checked. It is too much to ask every
|
||||
developer to build all BSPs and check.
|
||||
|
||||
RTEMS Kernel Symbols Tool
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The python tool `rtems-kern-symbols` can read a kernel header loading
|
||||
a previously generated version. This maintains the current symbol set
|
||||
without you needing to build the object files previously scanned.
|
||||
|
||||
The kernel namespace header can be regenerated from the original
|
||||
header. This checks the kernel header is already sorted. If you think
|
||||
there is a sorting issue in the existing header please regenerate
|
||||
without adding new symbols.
|
||||
|
||||
```
|
||||
$ ./rtems-kern-symbols --regenerate --output=tmp.h
|
||||
```
|
||||
|
||||
This command needs access to your built RTEMS tools. You can set your
|
||||
environment `PATH` variable or you can specify the top level path as an argument:
|
||||
```
|
||||
$ ./rtems-kern-symbols --rtems-tools=/opt/work/rtems/6
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
* You can provide a different kernel header using the `--kern-header`
|
||||
argument. The default is the LibbSD header.
|
||||
|
||||
* The `--report` option provides a report.
|
||||
|
||||
* The `--diff` option provides a unified diff of any changes.
|
||||
|
||||
* The `--write` option is needed to write any changes
|
||||
|
||||
* The `--output` option lets you control the output kernel header file
|
||||
change are written too
|
||||
|
||||
The tool manages a number of exlcuded symbols. These are symbols in
|
||||
the kernel space that are not mapped to the RTEMS kernel namespace.
|
||||
|
||||
How to Import Code from FreeBSD
|
||||
-------------------------------
|
||||
|
||||
@ -134,7 +210,7 @@ How to Import Code from FreeBSD
|
||||
* Immediately check in the imported files without the changes to `libbsd.py` and the buildsets. Do not touch the imported files yourself at this point.
|
||||
* Port the imported files to RTEMS. See 'Rules for Modifying FreeBSD Source'.
|
||||
* Add a test to the testsuite if possible.
|
||||
* Run `./create-kernel-namespace.sh` if you imported kernel space headers. Add only your new defines via `git add -p rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h`.
|
||||
* Run `./rtems-kern-symbols` as discussed above
|
||||
* Create one commit from this.
|
||||
|
||||
The -S or --stats option generates reports the changes we have made to
|
||||
|
@ -1,133 +0,0 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 embedded brains GmbH. All rights reserved.
|
||||
#
|
||||
# embedded brains GmbH
|
||||
# Dornierstr. 4
|
||||
# 82178 Puchheim
|
||||
# Germany
|
||||
# <rtems@embedded-brains.de>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# This script generates the kernel namespace header file
|
||||
# <machine/rtems-bsd-kernel-namespace.h>.
|
||||
#
|
||||
|
||||
objdump --syms `for i in build/*rtems* ; do \
|
||||
find $i/freebsd/sys/ -name '*.o' ; \
|
||||
echo $i/rtemsbsd/rtems/rtems-kernel-*.o ; \
|
||||
done` \
|
||||
| awk '/^[0-9a-f]+[[:blank:]]+g/ {print $6}' \
|
||||
| sed 's/^_bsd_//' \
|
||||
| sed '/^accept$/d' \
|
||||
| sed '/^arc4random$/d' \
|
||||
| sed '/^bind$/d' \
|
||||
| sed '/^blackhole$/d' \
|
||||
| sed '/^bpf_filter$/d' \
|
||||
| sed '/^bpf_jitter$/d' \
|
||||
| sed '/^bpf_jitter_enable$/d' \
|
||||
| sed '/^bpf_validate$/d' \
|
||||
| sed '/^connect$/d' \
|
||||
| sed '/^drop_redirect$/d' \
|
||||
| sed '/^drop_synfin$/d' \
|
||||
| sed '/^free$/d' \
|
||||
| sed '/^getentropy$/d' \
|
||||
| sed '/^getpeername$/d' \
|
||||
| sed '/^getsockname$/d' \
|
||||
| sed '/^getsockopt$/d' \
|
||||
| sed '/^ifqmaxlen$/d' \
|
||||
| sed '/^in6addr_any$/d' \
|
||||
| sed '/^in6addr_loopback$/d' \
|
||||
| sed '/^in6addr_nodelocal_allnodes$/d' \
|
||||
| sed '/^in6addr_linklocal_allnodes$/d' \
|
||||
| sed '/^kevent$/d' \
|
||||
| sed '/^kqueue$/d' \
|
||||
| sed '/^listen$/d' \
|
||||
| sed '/^malloc$/d' \
|
||||
| sed '/^max_datalen$/d' \
|
||||
| sed '/^max_hdr$/d' \
|
||||
| sed '/^max_linkhdr$/d' \
|
||||
| sed '/^max_protohdr$/d' \
|
||||
| sed '/^maxsockets$/d' \
|
||||
| sed '/^nd6_debug$/d' \
|
||||
| sed '/^nd6_delay$/d' \
|
||||
| sed '/^nd6_gctimer$/d' \
|
||||
| sed '/^nd6_maxnudhint$/d' \
|
||||
| sed '/^nd6_mmaxtries$/d' \
|
||||
| sed '/^nd6_onlink_ns_rfc4861$/d' \
|
||||
| sed '/^nd6_prune$/d' \
|
||||
| sed '/^nd6_umaxtries$/d' \
|
||||
| sed '/^nd6_useloopback$/d' \
|
||||
| sed '/^nmbclusters$/d' \
|
||||
| sed '/^nmbjumbo16$/d' \
|
||||
| sed '/^nmbjumbo9$/d' \
|
||||
| sed '/^nmbjumbop$/d' \
|
||||
| sed '/^nmbufs$/d' \
|
||||
| sed '/^nolocaltimewait$/d' \
|
||||
| sed '/^path_mtu_discovery$/d' \
|
||||
| sed '/^pause$/d' \
|
||||
| sed '/^pf_osfp_entry_pl$/d' \
|
||||
| sed '/^pf_osfp_pl$/d' \
|
||||
| sed '/^pipe$/d' \
|
||||
| sed '/^poll$/d' \
|
||||
| sed '/^random$/d' \
|
||||
| sed '/^realloc$/d' \
|
||||
| sed '/^reallocf$/d' \
|
||||
| sed '/^recvfrom$/d' \
|
||||
| sed '/^recvmsg$/d' \
|
||||
| sed '/^rtems/d' \
|
||||
| sed '/^select$/d' \
|
||||
| sed '/^sendmsg$/d' \
|
||||
| sed '/^sendto$/d' \
|
||||
| sed '/^setfib$/d' \
|
||||
| sed '/^setsockopt$/d' \
|
||||
| sed '/^shutdown$/d' \
|
||||
| sed '/^socket$/d' \
|
||||
| sed '/^socketpair$/d' \
|
||||
| sed '/^soreceive_stream$/d' \
|
||||
| sed '/^srandom$/d' \
|
||||
| sed '/^strdup$/d' \
|
||||
| sed '/^sysctlbyname$/d' \
|
||||
| sed '/^sysctl$/d' \
|
||||
| sed '/^sysctlnametomib$/d' \
|
||||
| sed '/sys_init/d' \
|
||||
| sed '/^taskqueue_/d' \
|
||||
| sed '/^tcp_offload_listen_start$/d' \
|
||||
| sed '/^tcp_offload_listen_stop$/d' \
|
||||
| sed '/^ticks$/d' \
|
||||
| sed '/^useloopback$/d' \
|
||||
| sed '/^_Watchdog_Ticks_since_boot$/d' \
|
||||
| sort -u > symbols.txt
|
||||
|
||||
cat << eof > rtems-bsd-kernel-namespace.h
|
||||
#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_KERNEL_SPACE_H_
|
||||
#error "the header file <machine/rtems-bsd-kernel-space.h> must be included first"
|
||||
#endif
|
||||
|
||||
eof
|
||||
sed 's/^\(.*\)/#define \1 _bsd_\1/' < symbols.txt >> rtems-bsd-kernel-namespace.h
|
||||
rm symbols.txt
|
||||
mv rtems-bsd-kernel-namespace.h rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h
|
505
rtems-kern-symbols
Executable file
505
rtems-kern-symbols
Executable file
@ -0,0 +1,505 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
"""RTEMS LibBBSD Kernel Symbols
|
||||
|
||||
Generate the symbols for the kernel headers and merge in any new ones
|
||||
"""
|
||||
|
||||
#
|
||||
# Copyright (C) 2021 Chris Johns <chrisj@rtems.org>, All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
version = "1.0"
|
||||
|
||||
kern_objects = [
|
||||
( 'freebsd/sys', '.*\.o' ),
|
||||
( 'rtemsbsd/rtems', 'rtems-kernel-.*\.o' )
|
||||
] # yapf: disable
|
||||
|
||||
kern_excludes = [
|
||||
'^rtems_',
|
||||
'^accept$',
|
||||
'^arc4random$',
|
||||
'^bind$',
|
||||
'^blackhole$',
|
||||
'^bootverbose$',
|
||||
'^bpf_filter$',
|
||||
'^bpf_jitter$',
|
||||
'^bpf_jitter_enable$',
|
||||
'^bpf_validate$',
|
||||
'^cache_enter$',
|
||||
'^connect$',
|
||||
'^drop_redirect$',
|
||||
'^drop_synfin$',
|
||||
'^free$',
|
||||
'^getentropy$',
|
||||
'^getpeername$',
|
||||
'^getsockname$',
|
||||
'^getsockopt$',
|
||||
'^global_epoch$',
|
||||
'^global_epoch_preempt$',
|
||||
'^ifqmaxlen$',
|
||||
'^in6addr_any$',
|
||||
'^in6addr_linklocal_allnodes$',
|
||||
'^in6addr_loopback$',
|
||||
'^in6addr_nodelocal_allnodes$',
|
||||
'^in_epoch$',
|
||||
'^kevent$',
|
||||
'^kqueue$',
|
||||
'^listen$',
|
||||
'^malloc$',
|
||||
'^max_datalen$',
|
||||
'^max_hdr$',
|
||||
'^max_linkhdr$',
|
||||
'^max_protohdr$',
|
||||
'^maxsockets$',
|
||||
'^nd6_debug$',
|
||||
'^nd6_delay$',
|
||||
'^nd6_gctimer$',
|
||||
'^nd6_maxnudhint$',
|
||||
'^nd6_mmaxtries$',
|
||||
'^nd6_onlink_ns_rfc4861$',
|
||||
'^nd6_prune$',
|
||||
'^nd6_umaxtries$',
|
||||
'^nd6_useloopback$',
|
||||
'^net_epoch$',
|
||||
'^net_epoch_preempt$',
|
||||
'^nmbclusters$',
|
||||
'^nmbjumbo16$',
|
||||
'^nmbjumbo9$',
|
||||
'^nmbjumbop$',
|
||||
'^nmbufs$',
|
||||
'^nolocaltimewait$',
|
||||
'^path_mtu_discovery$',
|
||||
'^pause$',
|
||||
'^pf_osfp_entry_pl$',
|
||||
'^pf_osfp_pl$',
|
||||
'^pipe$',
|
||||
'^poll$',
|
||||
'^pselect$',
|
||||
'^random$',
|
||||
'^realloc$',
|
||||
'^reallocf$',
|
||||
'^recvfrom$',
|
||||
'^recvmsg$',
|
||||
'^rtems',
|
||||
'^select$',
|
||||
'^sendmsg$',
|
||||
'^sendto$',
|
||||
'^setfib$',
|
||||
'^setsockopt$',
|
||||
'^shutdown$',
|
||||
'^socket$',
|
||||
'^socketpair$',
|
||||
'^soreceive_stream$',
|
||||
'^srandom$',
|
||||
'^strdup$',
|
||||
'^sysctlbyname$',
|
||||
'^sysctl$',
|
||||
'^sysctlnametomib$',
|
||||
'sys_init',
|
||||
'^taskqueue_',
|
||||
'^tcp_offload_listen_start$',
|
||||
'^tcp_offload_listen_stop$',
|
||||
'^ticks$',
|
||||
'^useloopback$',
|
||||
'^_Watchdog_Ticks_since_boot$'
|
||||
] # yapf: disable
|
||||
|
||||
kern_header = 'rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h'
|
||||
|
||||
|
||||
class exit(Exception):
|
||||
"""Base class for exceptions."""
|
||||
def __init__(self, code):
|
||||
self.code = code
|
||||
|
||||
|
||||
class error(Exception):
|
||||
"""Base class for exceptions."""
|
||||
def set_output(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class general_error(error):
|
||||
"""Raise for a general error."""
|
||||
def __init__(self, what):
|
||||
self.set_output('error: ' + str(what))
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self, cmd, cwd='.'):
|
||||
self.exit_code = 0
|
||||
self.output = None
|
||||
self.cmd = cmd
|
||||
self.cwd = cwd
|
||||
self.result = None
|
||||
|
||||
def run(self):
|
||||
|
||||
import subprocess
|
||||
|
||||
#
|
||||
# Support Python 2.6
|
||||
#
|
||||
if "check_output" not in dir(subprocess):
|
||||
|
||||
def f(*popenargs, **kwargs):
|
||||
if 'stdout' in kwargs:
|
||||
raise ValueError(
|
||||
'stdout argument not allowed, it will be overridden.')
|
||||
process = subprocess.Popen(stdout=subprocess.PIPE,
|
||||
*popenargs,
|
||||
**kwargs)
|
||||
output, unused_err = process.communicate()
|
||||
retcode = process.poll()
|
||||
if retcode:
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise subprocess.CalledProcessError(retcode, cmd)
|
||||
return output
|
||||
|
||||
subprocess.check_output = f
|
||||
|
||||
self.exit_code = 0
|
||||
try:
|
||||
if os.name == 'nt':
|
||||
cmd = ['sh', '-c'] + self.cmd
|
||||
else:
|
||||
cmd = self.cmd
|
||||
output = subprocess.check_output(cmd,
|
||||
cwd=self.cwd).decode("utf-8")
|
||||
self.output = output.split(os.linesep)
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
self.exit_code = cpe.returncode
|
||||
output = cpe.output.decode("utf-8")
|
||||
self.output = output.split(os.linesep)
|
||||
except OSError as ose:
|
||||
cs = ' '.join(cmd)
|
||||
if len(cs) > 80:
|
||||
cs = cs[:80] + '...'
|
||||
raise general_error('bootstrap failed: %s in %s: %s' % \
|
||||
(cs, self.cwd, (str(ose))))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
raise
|
||||
|
||||
|
||||
class kernel_symbols:
|
||||
def __init__(self, excludes):
|
||||
self.bsd_tag = '_bsd_'
|
||||
self.excludes = [re.compile(exc) for exc in excludes]
|
||||
self.bsps = {}
|
||||
self.header = {'source': [], 'symbols': []}
|
||||
self.output = {'source': [], 'symbols': []}
|
||||
self.analysis = {'mapped': [], 'unmapped': [], 'new': []}
|
||||
|
||||
@staticmethod
|
||||
def _find(base, spec):
|
||||
found = []
|
||||
filter = re.compile(spec[1])
|
||||
for root, dirs, files in os.walk(os.path.join(base, spec[0]),
|
||||
topdown=True):
|
||||
for f in files:
|
||||
if filter.match(f):
|
||||
found += [os.path.join(root, f)]
|
||||
return found
|
||||
|
||||
@staticmethod
|
||||
def _find_bsps(build):
|
||||
bsps = []
|
||||
filter = re.compile('^.*-rtems[0-9].*-.*')
|
||||
for name in os.listdir(build):
|
||||
if os.path.isdir(os.path.join(build, name)) and \
|
||||
filter.match(name) != None:
|
||||
bsps += [name]
|
||||
return bsps
|
||||
|
||||
@staticmethod
|
||||
def bsp_arch(bsp):
|
||||
bs = bsp.split('-')
|
||||
return bs[0] + '-' + bs[1]
|
||||
|
||||
def _clean(self, symbols):
|
||||
syms = []
|
||||
for sym in symbols:
|
||||
add = True
|
||||
for exclude in self.excludes:
|
||||
if exclude.search(sym) is not None:
|
||||
add = False
|
||||
break
|
||||
if add:
|
||||
syms += [sym]
|
||||
return sorted(list(set(syms)))
|
||||
|
||||
def load_header(self, header):
|
||||
with open(header, 'r') as h:
|
||||
self.header['source'] = h.read().splitlines()
|
||||
filter = re.compile('^#define\s')
|
||||
for line in self.header['source']:
|
||||
if filter.match(line) != None:
|
||||
ls = line.split()
|
||||
if len(ls) == 3:
|
||||
self.header['symbols'] += [ls[1]]
|
||||
self.header['symbols'] = self._clean(self.header['symbols'])
|
||||
|
||||
def load_symbols(self, specs, excludes, build, tools):
|
||||
bsps = self._find_bsps(build)
|
||||
for bsp in bsps:
|
||||
self.bsps[bsp] = {'output': [], 'objects': [], 'symbols': []}
|
||||
for spec in specs:
|
||||
self.bsps[bsp]['objects'] += self._find(
|
||||
os.path.join(build, bsp), spec)
|
||||
arch = self.bsp_arch(bsp)
|
||||
if tools is not None:
|
||||
cmd = os.path.join(tools, 'bin', arch + '-nm')
|
||||
else:
|
||||
cmd = arch + '-nm'
|
||||
nm = command([cmd] + self.bsps[bsp]['objects'])
|
||||
nm.run()
|
||||
self.bsps[bsp]['output'] = nm.output
|
||||
object = '-'
|
||||
syms = []
|
||||
for line in nm.output:
|
||||
if len(line) == 0:
|
||||
continue
|
||||
if line[-1] == ':':
|
||||
object = os.path.basename(line[:-1])
|
||||
continue
|
||||
ls = line.split()
|
||||
if len(ls) == 3:
|
||||
ls = ls[1:]
|
||||
if ls[0] in ['A', 'B', 'C', 'D', 'R', 'T', 'W']:
|
||||
sym = ls[1]
|
||||
if sym.startswith(self.bsd_tag):
|
||||
sym = sym[len(self.bsd_tag):]
|
||||
if sym in syms:
|
||||
print('warning: duplicate symbol: %s:%s: %s (%s)' %
|
||||
(bsp, object, sym, ls[1]))
|
||||
syms += [sym]
|
||||
self.bsps[bsp]['symbols'] += syms
|
||||
|
||||
def generate_header(self):
|
||||
self.output['source'] = [
|
||||
'/*', '* RTEMS Libbsd, this file is generated. Do not edit.', '*/',
|
||||
'#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_KERNEL_SPACE_H_',
|
||||
'#error "the header file <machine/rtems-bsd-kernel-space.h> must be included first"',
|
||||
'#endif', ''
|
||||
] + ['#define\t%s %s%s' % (sym, self.bsd_tag, sym) for sym in self.output['symbols']]
|
||||
|
||||
def write_header(self, header):
|
||||
with open(header, 'wb') as o:
|
||||
o.write(
|
||||
os.linesep.join(self.output['source'] + ['']).encode("utf-8"))
|
||||
|
||||
def write_sym_data(self):
|
||||
for bsp in self.bsps:
|
||||
arch = self.bsp_arch(bsp)
|
||||
with open('sym-data-' + arch + '.txt', 'w') as o:
|
||||
o.writelines(os.linesep.join(self.bsps[bsp]['output']))
|
||||
|
||||
def merge(self, symbols):
|
||||
self.output['symbols'] = \
|
||||
self._clean(self.output['symbols'] + symbols)
|
||||
|
||||
def merge_bsp(self):
|
||||
for bsp in self.bsps:
|
||||
self.merge(self.bsps[bsp]['symbols'])
|
||||
|
||||
def analyse(self):
|
||||
for bsp in self.bsps:
|
||||
for sym in self.bsps[bsp]['symbols']:
|
||||
if sym in self.header['symbols']:
|
||||
key = 'mapped'
|
||||
else:
|
||||
key = 'new'
|
||||
self.analysis[key] += [sym]
|
||||
for key in self.analysis:
|
||||
self.analysis[key] = self._clean(self.analysis[key])
|
||||
self.analysis['unmapped'] = [sym for sym in self.header['symbols'] if sym not in self.analysis['mapped']]
|
||||
|
||||
def diff(self):
|
||||
import difflib
|
||||
return list(
|
||||
difflib.unified_diff(self.header['source'], self.output['source']))
|
||||
|
||||
def report(self):
|
||||
out = [
|
||||
'Symbols:',
|
||||
' header : %d' % (len(self.header['symbols'])),
|
||||
' mapped : %d' % (len(self.analysis['mapped'])),
|
||||
' unmapped : %d' % (len(self.analysis['unmapped'])),
|
||||
' new : %d' % (len(self.analysis['new']))
|
||||
]
|
||||
max_len = 0
|
||||
for bsp in self.bsps:
|
||||
if max_len < len(bsp):
|
||||
max_len = len(bsp)
|
||||
out += ['BSPs: %*s Unmapped Total' % (max_len - 4, ' ')]
|
||||
for bsp in self.bsps:
|
||||
unmapped = len(self._clean(self.bsps[bsp]['symbols']))
|
||||
total = len(self.bsps[bsp]['symbols'])
|
||||
out += [' %-*s: %-8d %d' % (max_len, bsp, unmapped, total)]
|
||||
out += ['New:'] + [' ' + sym for sym in self.analysis['new']]
|
||||
out += ['Unmapped:'] + [' ' + sym for sym in self.analysis['unmapped']]
|
||||
return out
|
||||
|
||||
|
||||
def run(args):
|
||||
try:
|
||||
argsp = argparse.ArgumentParser(
|
||||
prog='rtems-kern-symbols',
|
||||
description="RTEMS LibBSD Kernel Symbols")
|
||||
argsp.add_argument('-t',
|
||||
'--rtems-tools',
|
||||
help='RTEMS Tools (default: %(default)s).',
|
||||
type=str,
|
||||
default=None)
|
||||
argsp.add_argument(
|
||||
'-w',
|
||||
'--write',
|
||||
action='store_true',
|
||||
help=
|
||||
'Write the header to the output file name (default: %(default)s).')
|
||||
argsp.add_argument(
|
||||
'-d',
|
||||
'--diff',
|
||||
action='store_true',
|
||||
help='Show a diff if the header has changed (default: %(default)s).'
|
||||
)
|
||||
argsp.add_argument(
|
||||
'-o',
|
||||
'--output',
|
||||
type=str,
|
||||
default=kern_header,
|
||||
help='output path to the write the header (default: %(default)s).')
|
||||
argsp.add_argument(
|
||||
'-b',
|
||||
'--build',
|
||||
type=str,
|
||||
default='build',
|
||||
help='path to the rtems libbsd build output (default: %(default)s).'
|
||||
)
|
||||
argsp.add_argument(
|
||||
'-K',
|
||||
'--kern-header',
|
||||
type=str,
|
||||
default=kern_header,
|
||||
help=
|
||||
'kernel header to load existing symbols from(default: %(default)s).'
|
||||
)
|
||||
argsp.add_argument(
|
||||
'-S',
|
||||
'--sym-data',
|
||||
action="store_true",
|
||||
help=
|
||||
'Write the BSP symbol data that is parsed (default: %(default)s).')
|
||||
argsp.add_argument(
|
||||
'-r',
|
||||
'--regenerate',
|
||||
action="store_true",
|
||||
help=
|
||||
'Regenerate the header file from the symbols in it, write option ignored (default: %(default)s).'
|
||||
)
|
||||
argsp.add_argument('-R',
|
||||
'--report',
|
||||
action="store_true",
|
||||
help='Generate a report (default: %(default)s).')
|
||||
argopts = argsp.parse_args(args[1:])
|
||||
|
||||
print('RTEMS LibBSD Kernel Symbols, %s' % (version))
|
||||
|
||||
if not os.path.exists(argopts.build):
|
||||
raise general_error('path does not exist: %s' % (argopts.build))
|
||||
|
||||
ks = kernel_symbols(kern_excludes)
|
||||
|
||||
ks.load_header(argopts.kern_header)
|
||||
|
||||
if argopts.regenerate:
|
||||
ks.merge(ks.header['symbols'])
|
||||
print('Regenerating: symbols: %d: %s' %
|
||||
(len(ks.output['symbols']), argopts.output))
|
||||
ks.generate_header()
|
||||
diff = ks.diff()
|
||||
if len(diff) == 0:
|
||||
print('info: no changes; header not updated')
|
||||
else:
|
||||
print('info: writing: %s' % (argopts.output))
|
||||
ks.write_header(argopts.output)
|
||||
raise exit(0)
|
||||
|
||||
ks.load_symbols(kern_objects, kern_excludes, argopts.build,
|
||||
argopts.rtems_tools)
|
||||
|
||||
if argopts.sym_data:
|
||||
ks.write_sym_data()
|
||||
|
||||
ks.analyse()
|
||||
ks.merge(ks.header['symbols'])
|
||||
ks.merge_bsp()
|
||||
ks.generate_header()
|
||||
|
||||
diff = ks.diff()
|
||||
if argopts.write:
|
||||
if len(diff) == 0:
|
||||
print('info: no changes; header not updated')
|
||||
else:
|
||||
print('info: writing: %s' % (argopts.output))
|
||||
ks.write_header(argopts.output)
|
||||
|
||||
if argopts.report:
|
||||
print(os.linesep.join(ks.report()))
|
||||
|
||||
if argopts.diff:
|
||||
print('Diff: %d' % (len(diff)))
|
||||
print(os.linesep.join(diff))
|
||||
|
||||
except general_error as gerr:
|
||||
print(gerr)
|
||||
print('RTEMS Kernel Symbols FAILED', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
log.notice('abort: user terminated')
|
||||
sys.exit(1)
|
||||
except exit as ec:
|
||||
sys.exit(ec.code)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run(sys.argv)
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user