core

make TAGS and cscope

FreeBSDから移植したOpenBSD用のMakefile。なおオリジナルな奴はOpenBSDに即したきめ細かい配慮がなされた作りになってる。勿論、その分は複雑だ。

CURDIR = /usr/src/OpenBSD-7.1/sys
dofiles:
        cd ${CURDIR}
        find conf dev arch/i386 kern lib sys -name '*.[chSsly]' -a -type f > cscope.files
        rm -f TAGS
        xargs etags -a < cscope.files
        cscope -k -buq -p4 -v

使いそうな部分だけのTAGSとcscopeを作ってみた。findで複数PATHを指定する所とxargsを単独で使う所が目から鱗ですよ。TAGSは作成の度に追加されちゃうので、事前に削除する事。

cscopeのスイッチは、カーネルモード(turns off the use of the default include dir)、 cross-reference、 Display the last n file path components、らしい。

core

普通にcoreと言ったら、ユーザーランドのマナーの悪いやつが出すアレだ。

#include <stdlib.h>
#include <stdio.h>

int sum = 0;

int add(int a, int b) {
    return a + b;
}

int main(int argc, char* argv[]) {
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    sum = add(a, b);

    printf("sum=%d\n", sum);
    return 0;
}

こんな変哲も無いやつでも、使いかたを誤ると即coreだ。

vbox$ ./a.out
Segmentation fault (core dumped)
vbox$ gdb -q a.out a.out.core
Reading symbols from a.out...
[New process 123861]

Core was generated by `a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.

#0  _libc_strtol (nptr=0x0, endptr=0x0, base=10)
    at /usr/src/lib/libc/stdlib/strtol.c:68
68                      c = (unsigned char) *s++;

お決まりの臨場はさておき、coreファイルって何者?

vbox$ readelf -a a.out.core
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              CORE (Core file)
  Machine:                           Intel 80386
   :

普通のアプリと同様な形式でした。なんて事が昔の某本に説明されてたなあ。こういうマニアックな本は大好きであります。

kvm

vbox$ fuser -f /home/sakae
/home/sakae: 35377c 6823c 29165c 37714c
vbox# fuser -N /var/crash/bsd.0 -M /var/crash/bsd.0.core -f /home/sakae
fuser: can't read process at f57b95f8

ちなみにfuserコマンドは指定したファイルがどのプロセスから利用されてるか調べるやつ。例では、ksh,tmux等が使ってるって分る。PIDの後ろのcはcurrent working directoryって目印を示す。

290                     if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID, -1, sizeof(*kf),
(gdb)
292                             errx(1, "%s", kvm_geterr(kd));
(gdb)
fuser: can't read process at f57b95f8
[Inferior 1 (process 96325) exited with code 01]

どのあたりのルーチン?

(gdb) s
kvm_getfiles (kd=0x7fc9a780, op=2, arg=-1, esize=624, cnt=0xcf7d85a4)
    at /usr/src/lib/libkvm/kvm_file2.c:140
140             if (ISALIVE(kd)) {

この際だからkvmのライブラリィーを見て億

vbox$ pwd
/usr/src/lib/libkvm
vbox$ ls *.[ch]
kvm.c               kvm_file.h          kvm_mips64.c        kvm_proc2.c
kvm_alpha.c         kvm_file2.c         kvm_ntfs.c          kvm_riscv64.c
kvm_amd64.c         kvm_getloadavg.c    kvm_powerpc.c       kvm_sh.c
kvm_arm.c           kvm_hppa.c          kvm_powerpc64.c     kvm_sparc64.c
kvm_arm64.c         kvm_i386.c          kvm_private.h       kvm_udf.c
kvm_cd9660.c        kvm_m88k.c          kvm_proc.c

ふーん、arch特有なものと共通なものの寄せ集めなのね。

で、大量にあるカーネルの情報を効率よく取り出す為に、

NAME
     kvm_nlist – retrieve symbol table names from a kernel image

SYNOPSIS
     #include <kvm.h>
     #include <nlist.h>

     int
     kvm_nlist(kvm_t *kd, struct nlist *nl);

こんな関数が用意されてる。こいつの元ネタは

vbox$ ls -l /var/db/kvm_bsd.db
-rw-r-----  1 root  kmem  2613248 May 17 13:39 /var/db/kvm_bsd.db
vbox$ file /var/db/kvm_bsd.db
/var/db/kvm_bsd.db: writable, regular file, no read permission

こんなDBが用意されてる。 kvm_mkdb を使って、構成するんだな。

add disk for swap

前回やったsavecoreの失敗。SWAPエリアが足りない疑惑を思い付いた。ならばSWAP用に豪華にDISKを増設しちゃえ。VirtualBOXにDISKを増設。See Also add disk mycase

メモリーを2Gにしてるんで、セオリー通りにその2倍プラス余裕を持たせる事にして、5Gにした。普段はSWAPしたら負けよと思っているんで、既存のシステムは雀の涙の設定だ。

vbox$ cat /etc/fstab
374dfbdba8ac84a9.b none swap sw
374dfbdba8ac84a9.a / ffs rw,wxallowed 1 1
/dev/wd1c /EXTd ffs rw 1 1
swap /tmp mfs rw,nodev,nosuid,-s=1024m 0 0
vbox$ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/wd0a      3.7G    1.8G    1.7G    52%    /
/dev/wd1c      7.7G    4.2G    3.1G    57%    /EXTd

SWAPな情報が出ていないので、改めて専用コマンドで確認

vbox$ pstat -T
70/7030 open files
   1536 vnodes
0M/133M swap space
vbox$ swapctl -l
Device      512-blocks     Used    Avail Capacity  Priority
/dev/wd0b       273041        0   273041     0%    0

じゃ追加したDISKがちゃんと認識されてるか確認。

vbox$ dmesg | grep wd
wd0 at pciide0 channel 0 drive 0: <VBOX HARDDISK>
wd0: 128-sector PIO, LBA, 4096MB, 8388608 sectors
wd1 at pciide0 channel 0 drive 1: <VBOX HARDDISK>
wd1: 128-sector PIO, LBA, 8192MB, 16777216 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
wd1(pciide0:0:1): using PIO mode 4, Ultra-DMA mode 2
wd2 at pciide0 channel 1 drive 1: <VBOX HARDDISK>
wd2: 128-sector PIO, LBA, 5120MB, 10485760 sectors
wd2(pciide0:1:1): using PIO mode 4, Ultra-DMA mode 2
root on wd0a (374dfbdba8ac84a9.a) swap on wd0b dump on wd0b

目出度く、wd2として認識された。IDEなセカンダリィーの2番目に位置するって言う位置付けだ。

少しDISKの扱い方法を調査。

ディスクの設定

make disk

まず、fdiskの登場で、DISKの全エリアをOpenBSD用にセットアップ

vbox# fdisk -i wd2
Do you wish to write new MBR? [n] y
Writing MBR at offset 0.
vbox# fdisk -e wd2
Enter 'help' for information
wd2: 1> p
Disk: wd2       geometry: 652/255/63 [10485760 Sectors]
Offset: 0       Signature: 0xAA55
            Starting         Ending         LBA Info:
 #: id      C   H   S -      C   H   S [       start:        size ]
-------------------------------------------------------------------------------
 0: 00      0   0   0 -      0   0   0 [           0:           0 ] unused
 1: 00      0   0   0 -      0   0   0 [           0:           0 ] unused
 2: 00      0   0   0 -      0   0   0 [           0:           0 ] unused
*3: A6      0   1   2 -    652 180  40 [          64:    10485696 ] OpenBSD
wd2: 1> w
Writing MBR at offset 0.
wd2: 1> q

次はラベルエディタを手動モードで起動して(Install時の用法)エリアを作成。全部をswap用にした。

vbox# disklabel -E  wd2
Label editor (enter '?' for help at any prompt)
wd2> p
OpenBSD area: 64-10485760; size: 10485696; free: 10485696
#                size           offset  fstype [fsize bsize   cpg]
  c:         10485760                0  unused
wd2> a b
offset: [64]
size: [10485696]
FS type: [swap]
wd2*> w
wd2> q
No label changes.

後は、ちゃんとSWAPになるかの確認と、boot時に有効になるようにfstabに追加。

vbox# swapctl -a /dev/wd2b
vbox# vi /etc/fstab
  :
/dev/wd2b none swap sw

まだこのSWAPは使用されていないので、VirtualBOXレベルでは3Mぐらいの消費であった

swapctl, vnconfig

上でも出てきたけど、普通はこうするみたい

Adding Swap Space for FreeBSD

OpenBSD tips and tricks - adding swap on the fly

vnconfigなんてのもあるんか。

make core

実際にカーネルのコアを作ってみる。現状のSWAPのエリア状況

vbox# top
  :
Memory: Real: 15M/52M act/tot Free: 1942M Cache: 20M Swap: 0K/5253M

じゃ、やるぞ

ddb{0}> call panic
 :
ddb{0}> boot dump
syncing disks...14 11  done
WARNING: not updating battery clock

dumping to dev 1, offset 8
dump 132 131 130 ... 7 6 5 4 3 2 1 0 area improper

rebooting...
>> OpenBSD/i386 BOOT 3.44
  :
avecore: reboot after panic: uvm_fault(0xd58e3960, 0x0, 0, 1) -> e
savecore: system went down at Sun Sep 25 15:01:35 2022
savecore: writing core to /var/crash/bsd.3.core
savecore: writing kernel to /var/crash/bsd.3
  :

確認したけど駄目だった。

vbox# fstat -N bsd.3 -M bsd.3.core
fstat: can't read process at f577a274

try2

優先順位を変更出来るみたいなので、、

vbox# swapctl -c -p 1 /dev/wd0b
vbox# swapctl -l
Device      512-blocks     Used    Avail Capacity  Priority
/dev/wd2b     10485696        0 10485696     0%    0
/dev/wd0b       273041        0   273041     0%    1
Total         10758737        0 10758737     0%

やっぱり駄目だわさ。何で?

db{0}> boot dump
syncing disks...12 8  done
WARNING: not updating battery clock

dumping to dev 1, offset 8
dump 132 131 130 129 ... 4 3 2 1 0 area improper

ふと気になった事

vbox# dmesg | grep wd
  :
root on wd0a (374dfbdba8ac84a9.a) swap on wd0b dump on wd0b

よくみると、swapとdumpは別物扱いされてるっぽいぞ。

where msg

上の疑問のメッセージを何処で出している? それはね、 kern/subr_disk.c

void
setroot(struct device *bootdv, int part, int exitflags)
{
   :
        printf("root on %s%c", rootdv->dv_xname, 'a' + part);

        if (dk && dk->dk_device == rootdv)
                printf(" (%s.%c)", duid_format(rootduid), 'a' + part);

        if (swdevt[0].sw_dev != NODEV)
                printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
                    DISKUNIT(swdevt[0].sw_dev),
                    'a' + DISKPART(swdevt[0].sw_dev));
        if (dumpdev != NODEV)
                printf(" dump on %s%d%c", findblkname(major(dumpdev)),
                    DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
        printf("\n");
}

どうもdumpdevは選択の余地が無いっぽい。

How to handle disk at install

ちょっとイジケてインストール中のDISKコマンドの使われ方をみておく。

src/distrib/i386/common/install.md

                ask "Use (W)hole disk$_q or (E)dit the MBR?" "$_d"
                case $resp in
                [wW]*)
                        echo -n "Setting OpenBSD MBR partition to whole $_disk..."
                        fdisk -iy $_disk >/dev/null
                        echo "done."
                        return ;;
                   :
md_prep_disklabel() {
        local _disk=$1 _f=/tmp/i/fstab.$1

        md_prep_fdisk $_disk

        disklabel_autolayout $_disk $_f || return
        [[ -s $_f ]] && return

        # Edit disklabel manually.
        # Abandon all hope, ye who enter here.
        disklabel -F $_f -E $_disk
}

DISKを全部使う場合は、-iy だ。それから、パーテションのレイアウトは全アーチで共通なので 、それを呼出ているんだな。

src/distrib/miniroot/install.sub

disklabel_autolayout() {
          :
        _qst="Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout?"
        while :; do
                echo "The auto-allocated layout for $_disk is:"
                disklabel -h -A $_disk | egrep "^#  |^  [a-p]:"
                ask "$_qst" a
                case $resp in
                [aA]*)  _op=-w;;
                [eE]*)  _op=-E;;
                [cC]*)  return 0;;
                *)      continue;;
                esac
                disklabel -F $_f $_op -A $_disk
                return
        done

なる程、よく分ったよ。

disklabel(8)を見ていたら、自動割付の計算値が紹介されてた。

Disks >= 10 Gigabytes
      /                5% of disk.  150M – 1G
      swap            10% of disk.   80M – 2x max physical memory
      /tmp             8% of disk.  120M – 4G
      /var            13% of disk.   80M – 4G + 2x size of crash dump
       :

スワップは最低80M以上必要で、実メモリーの2倍。/varは、80Mから4Gの範囲それに、クラッシュ用のエリアが2倍は必要。いわゆる死体は2名様まで受け入れる設備が必要って事だな。なお、死体すなわちkernelコアサイズは、色々だけど。。。

パーテションの切りかたに悩みがあったら、参考にすればよい。


This year's Index

Home