__ctype_b_loc它的目的是什么?

时间:2016-06-08 12:24:31

标签: reverse-engineering glibc

我试图理解使用Try {...} catch { $_.ErrorDetails += ('Letter: {0} Path: {1}' -f $_.letter, $_.path) throw $_ } 的一段代码,问题是我不知道这个函数的用途是什么。

到目前为止,我发现它已在__ctype_b_loc()中定义。我还找到了它的原型和实现。我仍然不知道这个功能是什么。

有人能让我高兴吗?

2 个答案:

答案 0 :(得分:13)

经过公平的研究,我想我可以回答这个问题。

unsigned short int __ctype_b_loc (void)

是一个返回指向' traits 的指针的函数。包含与每个单个字符的特征相关的一些标志的表。

这里带有标志的枚举:

来自ctype.h

enum
{
  _ISupper = _ISbit (0),        /* UPPERCASE.  */
  _ISlower = _ISbit (1),        /* lowercase.  */
  _ISalpha = _ISbit (2),        /* Alphabetic.  */
  _ISdigit = _ISbit (3),        /* Numeric.  */
  _ISxdigit = _ISbit (4),       /* Hexadecimal numeric.  */
  _ISspace = _ISbit (5),        /* Whitespace.  */
  _ISprint = _ISbit (6),        /* Printing.  */
  _ISgraph = _ISbit (7),        /* Graphical.  */
  _ISblank = _ISbit (8),        /* Blank (usually SPC and TAB).  */
  _IScntrl = _ISbit (9),        /* Control character.  */
  _ISpunct = _ISbit (10),       /* Punctuation.  */
  _ISalnum = _ISbit (11)        /* Alphanumeric.  */
};

举一个例子,如果您查找表__ctype_b_loc(),则返回其ascii代码为0x30的字符(' 0')您将有0x08d8

0x08d8=0000 1000 1101 1000 (Alphanumeric, Graphical, Printing, Hexadecimal, Numeric)

该表与计算机上安装的语言环境的localchar相关联,因此与您在系统上的结果相比,该示例可能不准确。

答案 1 :(得分:3)

Alessandro自己的回答非常有用,但我想补充一些信息。

如Alessandro所述,__ctype_b_loc(void)函数返回一个数组,其中每个元素都包含一个ASCII字符的特征。例如,通过查看表格,我们可以了解到角色' A'是大写,十六进制,图形,打印,字母数字。

准确地说,__ctype_b_loc()函数返回const unsigned short int**,它是指向384 unsigned short int*数组的指针。 有ara 384元素的原因是表格可以被索引:

  • 任何unsigned char值[0,255](所以256个元素)
  • EOF(-1)
  • 任何signed char值[-128,-1)(所以127个元素)

此表由函数使用:

  • isupper
  • islower判断
  • 因而isalpha
  • ispunct判断
  • ...

但是这些函数被定义为宏,因此您永远不会在汇编代码中看到它们被调用。您将看到调用__ctype_b_loc()来获取表,使用一些代码来检索正确的条目以及使用位掩码来查看我们正在检查的属性是否已设置。例如,如果我们想查看字符是否为大写,我们必须检查是否设置了位。

这是通过调用isupper('A');生成的汇编代码:

call sym.imp.__ctype_b_loc  ; isupper('A');
mov rax, qword [rax]        ; get the pointer to the array of 'unsigned short int*'
movsx rdx, byte 0x41        ; prepare to look up for character 'A'
add rdx, rdx                ; each entry is 2 bytes, so we double the value of 'A'
add rax, rdx                ; look up for 'A' in the table
movzx eax, word [rax]       ; get the 'unsigned short int' containing the properties
movzx eax, ax               
and eax, 0x100              ; 0x0100 in little-endian is 0x0001 in big-endian (check if bit 0 is set)