顯示具有 Debug 標籤的文章。 顯示所有文章
顯示具有 Debug 標籤的文章。 顯示所有文章

2016年5月30日 星期一

編譯 Ubuntu 的 Linux kernel 來使用 USB to RS-232 輸出訊息

如果曾經有參加過台北的 Ubuntu Hardware Summit,應該都會拿到一本橘色小手冊 Ubuntu Debugging,當中有提到可以設定幾個 Linux kernel 編譯選項中

CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_PL2303=y

然後就可以在 Linux kernel 開機參數加上

console=tty console=ttyUSB0,115200n8

這樣就可以透過 USB to RS-232 傳輸線將 Linux kernel 訊息輸出到另外一台電腦上面,為什麼要這樣做有時候是因為 Linux kernel 開機時是什麼畫面也沒有,也不曉得中間到底發生了什麼事情,又或者是 Linux kernel 訊息出現的太快了,來不及看清楚完整的訊息一下子就過去了,也沒有來得及儲存到檔案系統上面就當機了,有著許許多多不同的情況可能會需要。

但是實際上要怎麼做才能夠編譯出 Ubuntu 上面所使用的 Linux kernel 呢?

首先是將 Ubuntu 所使用的 Linux kernel 的原始碼下載回來。

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git

然後我自己 commit 了一些修改 (主要是針對 amd64)。

$ git diff HEAD^..HEAD
diff --git a/debian.master/abi/4.4.0-22.39/amd64/generic.modules b/debian.master/abi/4.4.0-22.39/amd64/generic.modules
index e1b9392..53d7914 100644
--- a/debian.master/abi/4.4.0-22.39/amd64/generic.modules
+++ b/debian.master/abi/4.4.0-22.39/amd64/generic.modules
@@ -2873,7 +2873,6 @@ pixcir_i2c_ts
 pkcs7_test_key
 pktcdvd
 pktgen
-pl2303
 platform_lcd
 plat_nand
 plat-ram
@@ -4236,7 +4235,6 @@ usblp
 usbmon
 usbmouse
 usbnet
-usbserial
 usb-serial-simple
 usbsevseg
 usb-storage
diff --git a/debian.master/config/annotations b/debian.master/config/annotations
index 825012f..167ab6e 100644
--- a/debian.master/config/annotations
+++ b/debian.master/config/annotations
@@ -6609,7 +6609,7 @@ CONFIG_USB_STORAGE_ENE_UB6250                   policy<{'amd64': 'm', 'arm64': '
 CONFIG_USB_UAS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 
 # Menu: Device Drivers >> USB support >> Support for Host-side USB >> USB Serial Converter support
-CONFIG_USB_SERIAL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL                               policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_GENERIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'powerpc': 'y', 'ppc64el': 'y'}>
 CONFIG_USB_SERIAL_SIMPLE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_AIRCABLE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
@@ -6641,7 +6641,7 @@ CONFIG_USB_SERIAL_MOS7715_PARPORT               policy<{'amd64': 'y', 'arm64': '
 CONFIG_USB_SERIAL_MOS7840                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_MXUPORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_NAVMAN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
-CONFIG_USB_SERIAL_PL2303                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_PL2303                        policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_OTI6858                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_QCAUX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_QUALCOMM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index 505a3c7..7cb1284 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -8391,7 +8391,8 @@ CONFIG_USB_RIO500=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
 CONFIG_USB_S2255=m
-CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
 CONFIG_USB_SERIAL_AIRCABLE=m
 CONFIG_USB_SERIAL_ARK3116=m
 CONFIG_USB_SERIAL_BELKIN=m
@@ -8439,7 +8440,7 @@ CONFIG_USB_SERIAL_OMNINET=m
 CONFIG_USB_SERIAL_OPTICON=m
 CONFIG_USB_SERIAL_OPTION=m
 CONFIG_USB_SERIAL_OTI6858=m
-CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_PL2303=y
 CONFIG_USB_SERIAL_QCAUX=m
 CONFIG_USB_SERIAL_QT2=m
 CONFIG_USB_SERIAL_QUALCOMM=m

接著開始編譯 Linux kernel (在有八個 CPU cores 的電腦上)

$ CONCURRENCY_LEVEL=8 fakeroot debian/rules clean binary-generic

最後就會在上層目錄產生 Ubuntu 所使用的 Linux kernel 的 Debian packages 了。

$ ls -1 ../*.deb
../linux-cloud-tools-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-headers-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-image-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-image-extra-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-tools-4.4.0-22-generic_4.4.0-22.40_amd64.deb

這樣就可以將這些 Debian packages 拿去安裝使用了。

最後我放了一份在 http://people.ubuntu.com/~fourdollars/usb2rs232/ 上面,也許有人剛好也需要想要測試一下效果如何。

參考資料:https://wiki.ubuntu.com/Kernel/KernelDebuggingTricks

2013年8月7日 星期三

使用 GDB 追縱執行中程式裡面的變數值

首先是要安裝 debug symbols 的套件來使用。

Debian 可以參考 HowToGetABacktrace - Debian Wiki
Ubuntu 可以參考 DebuggingProgramCrash - Ubuntu Wiki

例如目標是 Ubuntu 12.04 中的 Xorg 裡面的 positionSprite() 函式在執行時傳入的變數值,所以先用

$ ps aux | grep X
root      1044  0.4  1.0 127440 21524 tty7     Ss+  18:44   0:06 /usr/bin/X :0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch -background none
u         2633  0.0  0.0  13616   928 pts/2    S+   19:11   0:00 grep --color=auto X
來找出 Xorg 的 PID

然後執行以下指令:

$ sudo gdb /usr/bin/Xorg 1044                                                                                                                                                                         
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /usr/bin/Xorg...Reading symbols from /usr/lib/debug/usr/bin/Xorg...done.
done.
Attaching to program: /usr/bin/Xorg, process 1044
Reading symbols from /lib/x86_64-linux-gnu/libudev.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libudev.so.0
... [省略]
(gdb) set height 0
(gdb) break positionSprite
Breakpoint 1 at 0x7fedc71d1140: file ../../dix/getevents.c, line 940.
(gdb) c
Continuing.

Breakpoint 1, positionSprite (dev=0x7fedc94105d0, mode=0, mask=0x7fff3c6e6780, devx=0x7fff3c6e6770, devy=0x7fff3c6e6778, screenx=0x7fff3c6e6760, screeny=0x7fff3c6e6768) at ../../dix/getevents.c:940
940     ../../dix/getevents.c: 沒有此一檔案或目錄.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>print *devx
>print *devy
>print *screenx
>print *screeny
>continue
>end
(gdb) c
Continuing.

接下來移動滑鼠就可以看到以下的訊息。

Breakpoint 1, positionSprite (dev=0x7fedc94105d0, mode=0, mask=0x7fff3c6e6780, devx=0x7fff3c6e6770, devy=0x7fff3c6e6778, screenx=0x7fff3c6e6760, screeny=0x7fff3c6e6768) at ../../dix/getevents.c:940
940     in ../../dix/getevents.c
$45 = 1023.4510981145139
$46 = 757.60130195816362
$47 = 1366.6023460649326
$48 = 758.58904811456273

Breakpoint 1, positionSprite (dev=0x7fedc94105d0, mode=0, mask=0x7fff3c6e6780, devx=0x7fff3c6e6770, devy=0x7fff3c6e6778, screenx=0x7fff3c6e6760, screeny=0x7fff3c6e6768) at ../../dix/getevents.c:940
940     in ../../dix/getevents.c
$49 = 1022.651098102593
$50 = 757.60130195816362
$51 = 1365.5341153549775
$52 = 758.58904811456273

可以將設定好的 breakpoints 的動作儲存成一個腳本檔

(gdb) save breakpoints break.cmd
Saved to file 'break.cmd'.

腳本的內容是:

set height 0
break positionSprite
  commands
    print *devx
    print *devy
    print *screenx
    print *screeny
    cont
  end

只是第一行的 set height 0 是手動加上去的,目的是不要訊息過長就停下來。

下次再使用 GDB 時就可以執行 source 載入使用。

(gdb) source break.cmd 
Breakpoint 1 at 0x7fedc71d1140: file ../../dix/getevents.c, line 940.
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00007fedc71d1140 in positionSprite at ../../dix/getevents.c:940
        print *devx
        print *devy
        print *screenx
        print *screeny
        cont

只是前面有一個找不到原始碼的小問題,可以執行以下指令來下載原始碼:

$ apt-get source xserver-xorg-core-lts-quantal
或是:
$ pull-lp-source xorg-server-lts-quantal precise

然後再執行:

$ sudo gdb /usr/bin/Xorg 1044 -d xorg-server-lts-quantal-1.13.0

最後 GDB 有其它的 Frontend 可以使用,像是 cgdb 以及 ddd 在這裡就不多提了。

2013年7月31日 星期三

Linux 電源供應的系統資訊

在筆記型電腦或是使用藍牙裝置時,系統上面都會有電源供應的資訊。

只要在 /sys/devices 底下找尋 power_supply 的目錄就可以找到。

如下所示:

u@u:/sys/devices$ find -name power_supply | while read path; do ls -l $(dirname $path); done
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../../../../../bus/hid/drivers/apple
drwxr-xr-x 3 root root    0 Jul 31 17:38 hidraw
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:39 power_supply
-r--r--r-- 1 root root 4096 Jul 31 17:42 report_descriptor
lrwxrwxrwx 1 root root    0 Jul 31 17:38 subsystem -> ../../../../../../../../../../bus/hid
-rw-r--r-- 1 root root 4096 Jul 31 17:38 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../../../../../bus/hid/drivers/magicmouse
drwxr-xr-x 3 root root    0 Jul 31 17:39 hidraw
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:39 power_supply
-r--r--r-- 1 root root 4096 Jul 31 17:42 report_descriptor
lrwxrwxrwx 1 root root    0 Jul 31 17:39 subsystem -> ../../../../../../../../../../bus/hid
-rw-r--r-- 1 root root 4096 Jul 31 17:39 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../bus/acpi/drivers/battery
-r--r--r-- 1 root root 4096 Jul 31 17:42 hid
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
-r--r--r-- 1 root root 4096 Jul 31 17:42 path
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:36 power_supply
lrwxrwxrwx 1 root root    0 Jul 31 17:36 subsystem -> ../../../../../../bus/acpi
-rw-r--r-- 1 root root 4096 Jul 31 17:36 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../bus/acpi/drivers/ac
-r--r--r-- 1 root root 4096 Jul 31 17:42 hid
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
-r--r--r-- 1 root root 4096 Jul 31 17:42 path
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:36 power_supply
lrwxrwxrwx 1 root root    0 Jul 31 17:36 subsystem -> ../../../../../../bus/acpi
-rw-r--r-- 1 root root 4096 Jul 31 17:36 uevent

所以可以從 driver 這個 symbolic link 看出每個電源供應是屬於哪些裝置。

另外也可以使用指令來監測 udev 裡面關於 power_supply 的訊息。

如下所示:

u@u:~$ udevadm monitor --subsystem-match=power_supply                                                                                                                                                      
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[65.358427] change   /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:13/0005:05AC:030D.0002/power_supply/hid-AB:CD:EF:12:34:56-battery (power_supply)
UDEV  [65.398449] change   /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:13/0005:05AC:030D.0002/power_supply/hid-AB:CD:EF:12:34:56-battery (power_supply)
KERNEL[81.032204] change   /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/PNP0C0A:00/power_supply/BAT1 (power_supply)
UDEV  [81.033615] change   /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/PNP0C0A:00/power_supply/BAT1 (power_supply)

最後就是 Freedesktop 有一個 UPower 專案,專門用來提供底層電源資訊的介面給桌面應用程式來使用。

如果是在 GNOME 桌面環境底下就是 gnome-settings-daemon 與 gnome-power-manager 透過 DBus 來使用 UPower 以提供圖形介面給桌面使用者使用。

2013年7月22日 星期一

GRUB2 的除錯訊息

GRUB2 的除錯很麻煩,因為有些問題只會在特定硬體上發生,所以無法使用其它軟體模擬的方式進行,不過還好 GRUB2 本身就內建一個除錯訊息的環境變數就叫做 debug

在 Debian/Ubuntu 底下可以直接修改 /boot/grub/grub.cfg 在最前面加上 set debug=all 就可以在執行 GRUB2 時將所有的除錯訊息都列印在電腦螢幕上面,不過更好的方式是在 /etc/grub.d/ 底下建立一個 shell script 來 echo 出 set debug=all

只是這種作法只能使用在 GRUB2 去硬碟上面讀取 /boot/grub/grub.cfg 之後的除錯訊息,另外就是除錯訊息本身太多太雜,反而會有一種見林不見樹的感覺。

所以這個時候可以使用一些小技巧將 debug 訊息的分類 (category) 都找出來,然後去掉不想要的部份再使用在 debug 參數設定上面。

例如我們可以在 GRUB2 的原始碼裡面執行以下指令:

~/grub2-1.99$ grep grub_dprintf * -Irh | sed 's/[[:space:]]\+//g' | grep '^grub_dprintf("' | cut -d '"' -f 2 | sort -u | grep -v scripting | grep -v lexer | xargs echo | sed 's/ /,/g'
acpi,affs,ata,atkeyb,badram,bsd,btrfs,datetime,devalias,deviceiter,disk,drivemap,efi,efidisk,efiemu,elf,expand,fat,fb,fs,gettext,gpt,hostdisk,keystatus,linux,loader,memdisk,mmap,modules,multiboot_loader,ohci,partition,play,raid,reiserfs,reiserfs_blocktype,reiserfs_tree,relocator,scsi,uhci,usb,usb_keyboard,usbms,video,xnu,zfs

( 截取的方法也有很多可以參考此噗的討論 )

上面的指令將 scripting 跟 lexer 這兩個最囉唆的分類給去掉了,所以 GRUB2 的設定變成 set debug=acpi,affs,ata,atkeyb,badram,bsd,btrfs,datetime,devalias,deviceiter,disk,drivemap,efi,efidisk,efiemu,elf,expand,fat,fb,fs,gettext,gpt,hostdisk,keystatus,linux,loader,memdisk,mmap,modules,multiboot_loader,ohci,partition,play,raid,reiserfs,reiserfs_blocktype,reiserfs_tree,relocator,scsi,uhci,usb,usb_keyboard,usbms,video,xnu,zfs 就可以少掉很多訊息了。

另外就是去修改 GRUB2 原始碼加上自己的除錯訊息,像是:

grub_dprintf ("debug", "Your debug messages here\n");

然後重編 GRUB2 再安裝到系統上,再使用 set debug=debug 或是加到原本那一串長長的清單後面。

最後,linux 這個分類算是從 GRUB2 進入 Linux kernel 最重要的點,所以可以使用 set debug=linux 就可以看出系統是停在 GRUB2 裡面還是死在 Linux kernel 裡面。

還有最後的最後就是要將 /etc/default/grub 裡面的 GRUB_TERMINAL=console 打開,再執行 update-grub 才會有比較容易閱讀的除錯訊息,當然也許會有一些 Side Effect 的產生。

2019/12/19 補充:或是修改 grub-common 的 /etc/grub.d/40_custom 在最後加上 set debug=linux 再執行 sudo update-grub 就不用每次安裝更新 kernel 時,還要去編輯 /boot/grub/grub.cfg

2013年3月15日 星期五

關於 Thunderbird 在 IMAP 上使用郵件篩選中的自訂標頭的問題

過去一直很困擾這個問題,不過今天找到了一些解決方法,在此記錄一下。

首先來看 thunderbird-17.0.4+build1/mailnews/imap/src/nsImapProtocol.cpp 中的一段程式碼

// read in the accept languages preference
if (prefBranch)
{
  if (!gInitialized)
    GlobalInitialization(prefBranch);

  nsCOMPtr prefString;
  prefBranch->GetComplexValue("intl.accept_languages",
                              NS_GET_IID(nsIPrefLocalizedString),
                              getter_AddRefs(prefString));
  if (prefString)
    prefString->ToString(getter_Copies(mAcceptLanguages));

  nsCString customDBHeaders;
  prefBranch->GetCharPref("mailnews.customDBHeaders",
                          getter_Copies(customDBHeaders));

  ParseString(customDBHeaders, ' ', mCustomDBHeaders);                             
  prefBranch->GetBoolPref("mailnews.display.prefer_plaintext", &m_preferPlainText);
}

這段程式碼裡面使用的是 mailnews.customDBHeaders 但是在使用自訂標頭後是卻是儲存在 mailnews.customHeaders

然後再看一下同一個檔案中的另外一段程式碼

if (!downloadAllHeaders)  // if it's ok -- no filters on any header, etc.
{                                                                                        
  char *headersToDL = nullptr;
  char *what = nullptr;
  const char *dbHeaders = (gUseEnvelopeCmd) ? IMAP_DB_HEADERS : IMAP_ENV_AND_DB_HEADERS;
  nsCString arbitraryHeaders;
  GetArbitraryHeadersToDownload(arbitraryHeaders);
  for (uint32_t i = 0; i < mCustomDBHeaders.Length(); i++)
  {
    if (arbitraryHeaders.Find(mCustomDBHeaders[i], CaseInsensitiveCompare) == kNotFound)
    {
      if (!arbitraryHeaders.IsEmpty())
        arbitraryHeaders.Append(' ');
      arbitraryHeaders.Append(mCustomDBHeaders[i]);
    }
  }
  if (arbitraryHeaders.IsEmpty())
    headersToDL = strdup(dbHeaders);
  else
    headersToDL = PR_smprintf("%s %s",dbHeaders, arbitraryHeaders.get());

  if (gUseEnvelopeCmd)
    what = PR_smprintf(" ENVELOPE BODY.PEEK[HEADER.FIELDS (%s)])", headersToDL);
  else
    what = PR_smprintf(" BODY.PEEK[HEADER.FIELDS (%s)])",headersToDL);
  NS_Free(headersToDL);
  if (what)
  {
    commandString.Append(" %s (UID ");
     if (m_isGmailServer)
      commandString.Append("X-GM-MSGID X-GM-THRID X-GM-LABELS ");
    if (aolImapServer)
      commandString.Append(" XAOL.SIZE") ;
    else
      commandString.Append("RFC822.SIZE");
    commandString.Append(" FLAGS");
    commandString.Append(what);
    PR_Free(what);
  }
  else
  {
    commandString.Append(" %s (UID RFC822.SIZE BODY.PEEK[HEADER] FLAGS)");
  }
}

搭配前一段程式碼一起來看,應該是使用空白當分隔符號來進行不分大小寫的比對,於是我就手動將 mailnews.customHeaders 的內容複製到 mailnews.customDBHeaders 裡面並且去掉了冒號,接著重新啟動 Thunderbird 了。

不過卻發現收件匣當中的郵件還是無法篩選到,於是就注意到前面第二段程式碼最前面的 downloadAllHeaders,想說會不會是因為 IMAP 的關係,之前已經儲存在本地端的郵件的 DB 並沒有儲存這些資訊,應該要設法再讓 Thunderbird 重新抓取郵件的標頭, 於是我就將郵件移往其它的目錄再做篩選,果然就可以正常運作了。

另外我找到了一個似乎有相關的修正 Bug 363238 - saved searches fail for searches on x-headers, r=irving,只是目前它並不存在 Thunderbird 裡面就是了。