GVKun编程网logo

Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器

1

在这篇文章中,我们将为您详细介绍Linux内核(x86-64)程序集,用于将`structpt_regs`解码为系统调用中的寄存器的内容。此外,我们还会涉及一些关于(C)用bsearch在struct

在这篇文章中,我们将为您详细介绍Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器的内容。此外,我们还会涉及一些关于(C) 用 bsearch 在 struct 数组中按名称查找 struct、C ++中''struct''和''typedef struct''之间的区别?、C ++中''struct''和''typedef struct''之间的区别? - Difference between ''struct'' and ''typedef struct'' in C++?、c – ‘struct(*)[]’和’struct * []’之间有什么区别?的知识,以帮助您更全面地了解这个主题。

本文目录一览:

Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器

Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器

如何解决Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器

我已在基于 struct pt_regs 的 x86-64 系统调用上阅读了此 LWN article。

我不明白 struct pt_regs * 被解码成寄存器的方式。

确实,%rdi 保存了 struct pt_regs * 的地址,因此 (%rdi) 是内存中实际的 struct pt_regs

但是第一行mov 0x70(%rdi),%rdi改变了%rdi,那么我如何用来解码剩余的寄存器,%rsi%rdx%rcx,在调用 SyS_recv 之前?

LWN 文章除外:

asmlinkage long sys_recv(struct pt_regs *regs)
{
    return SyS_recv(regs->di,regs->si,regs->dx,regs->r10);
}

然后该函数的汇编变成,稍微重新排序 时尚:

<sys_recv>:
callq   <__fentry__>

/* decode regs->di,->si,->dx and ->r10 */
mov 0x70(%rdi),%rdi
mov 0x68(%rdi),%rsi
mov 0x60(%rdi),%rdx
mov 0x38(%rdi),%rcx

/* [ SyS_recv() is inlined here by the compiler,as it is tiny ] */
/* clear %r9 and %r8,the 5th and 6th args */
xor %r9d,%r9d
xor %r8d,%r8d

/* do the actual work */
callq   __sys_recvfrom

/* cleanup and return */
cltq
retq

(C) 用 bsearch 在 struct 数组中按名称查找 struct

(C) 用 bsearch 在 struct 数组中按名称查找 struct

如何解决(C) 用 bsearch 在 struct 数组中按名称查找 struct

我正在尝试实现函数 (1),以便在 struct 数组中按名称查找特定产品。 p_array 是包含 n 个产品的结构体数组,search_key 是指向具有搜索结构名称的字符串的指针 cmp 是指向我已实现的另一个函数 (2) 的指针。

/* (1) */
const Product* findProduct(const Product* p_array,const char* search_key,int (*cmp)(const void*,const void*))
{
    return bsearch(&search_key,p_array,100,sizeof(Product),cmp);
    
}

/* (2) */
int compareAlpha(const void* a,const void* b)
{
    const struct Product *shop_a = a;
    const struct Product *shop_b = b;

    int ret = strcmp(shop_a->name,shop_b->name);
    
    return ret;
}

我有以下问题:

  1. 我想不出办法找出 p_array 的长度
  2. 启动程序导致分段错误,我不知道为什么

我的主要功能是:

void printProducts(Product* array)
{
    int i = 0;
    while(array[i].name[0] != 0)
    {
        printf("product: %s\\tprice: %f\\t in stock: %d\\n",array[i].name,array[i].price,array[i].in_stock);
        i++;
    }
}

int main()
{
    Product array[6] = {
    {"peanut butter",1.2,5},{"cookies",12.3,23},{"cereals",3.2,12},{"bread",2.7,{"butter",4.2,{"\\0",0.0,0}
    };

    qsort(array,5,compareAlpha);
    printf("sorted lexically:\\n");
    printProducts(array);
    
    const Product* search = findProduct(array,"cookies",compareAlpha);
    if(search)
    {
        printf("Found product:\\n");
        printf("%s\\n",search->name);
    }

    qsort(array,compareNum);
    printf("sorted by in stock:\\n");
    printProducts(array);

    return 0;
}

想要的输出是

sorted lexically:
product: bread price: 2.700000 in stock: 12
product: butter price: 4.200000 in stock: 5
product: cereals price: 3.200000 in stock: 12
product: cookies price: 12.300000 in stock: 23
product: peanut butter price: 1.200000 in stock: 5
Found product:
cookies
Product not found!
sorted by in stock:
product: cookies price: 12.300000 in stock: 23
product: bread price: 2.700000 in stock: 12
product: cereals price: 3.200000 in stock: 12
product: butter price: 4.200000 in stock: 5
product: peanut butter price: 1.200000 in stock: 5

解决方法

您的代码中有几个错误:

  1. 无法在您的 compareAlpha() 函数中进行转换。你应该写const struct Product* shop_a = (const struct Product*)a;
  2. 在您的 printProducts() 函数中,您应该将 array[i].name[0] 与空字符 ''\\0'' 进行比较,而不是 0,即 while(array[i].name[0] != ''\\0'')
  3. array 函数中传递参数 printProducts() 会生成警告。您将 array 声明为静态数组而不是指针(尽管它是固有实现的并且可以作为指针访问),这会生成警告。你应该像这样传递它 void printProducts(Product array[])
  4. findProduct() 函数中,当您调用 bsearch() 函数时,您将要搜索的参数作为 &search_key 传递。您应该在没有 & 的情况下传递它。
  5. findProduct() 的返回类型应该是 void* 而不是 const Product*,因为 bsearch() 函数的返回类型是 void*。所以,在你得到一个返回值之后 findProduct() 函数,您需要将其类型转换为 const Product*
  6. 您在某些地方使用 struct 类型时没有使用 Product 关键字。在 C++ 中,它是可选的,但在 C 中它是强制性的。

  1. 我想不出办法找出 p_array 的长度

您可以像这样找到数组的大小 int size = sizeof(array) / sizeof(array[0]); 虽然不推荐这样做,因为它依赖于编译器。


  1. 启动程序导致分段错误,我不知道为什么

以下是修正了所有上述错误/警告的完整代码。

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

struct Product{
    char name[100];
    double price;
    int in_stock;
};

int compareAlpha(const void* a,const void* b)
{
    const struct Product* shop_a = (const struct Product*)a;
    const struct Product* shop_b = (const struct Product*)b;

    int ret = strcmp(shop_a->name,shop_b->name);

    return ret;
}

int compareNum(const void* a,const void* b)
{
    const struct Product* shop_a = (const struct Product*)a;
    const struct Product* shop_b = (const struct Product*)b;

    int ret = shop_a->in_stock <= shop_b->in_stock;

    return ret;
}

void* findProduct(struct Product p_array[],const char* search_key,int (*cmp)(const void*,const void*))
{
    return bsearch(search_key,(void*)p_array,5,sizeof(struct Product),cmp);

}



void printProducts(struct Product array[])
{
    int i = 0;
    while(array[i].name[0] != ''\\0'')
    {
        printf("product: %s\\tprice: %f\\t in stock: %d\\n",array[i].name,array[i].price,array[i].in_stock);
        i++;
    }
}

int main()
{
    struct Product array[6] = {
        {"peanut butter",1.2,5},{"cookies",12.3,23},{"cereals",3.2,12},{"bread",2.7,{"butter",4.2,{"\\0",0.0,0}
    };

    qsort(array,compareAlpha);
    printf("sorted lexically:\\n");
    printProducts(array);

    const struct Product* search = (const struct Product*)findProduct(array,"cookies",compareAlpha);
    if(search)
    {
        printf("Found product:\\n");
        printf("%s\\n",search->name);
    }else{
        printf("Product not found!\\n");
    }

    qsort(array,compareNum);
    printf("sorted by in stock:\\n");
    printProducts(array);

    return 0;
}

C ++中''struct''和''typedef struct''之间的区别?

C ++中''struct''和''typedef struct''之间的区别?

在C ++中,之间有什么区别:

struct Foo { ... };

typedef struct { ... } Foo;

#1楼

您不能对typedef结构使用forward声明。

struct本身是一个匿名类型,因此您没有实际名称来转发声明。

typedef struct{
    int one;
    int two;
}myStruct;

像这样的前瞻声明不会起作用:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: ''myStruct'' : redefinition; different basic types

#2楼

C ++中''typedef struct''和''struct''之间的一个重要区别是''typedef structs''中的内联成员初始化将不起作用。

// the ''x'' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the ''x'' in this struct WILL be initialised to zero
struct Foo { int x = 0; };

#3楼

Struct是创建数据类型。 typedef用于设置数据类型的昵称。


#4楼

C ++没有区别,但是我相信它会允许你在不明确地执行的情况下声明struct Foo的实例:

struct Foo bar;

#5楼

在C ++中,只有一个微妙的区别。 这是C的延续,它有所作为。

C语言标准( C89§3.1.2.3 , C99§6.2.3和C11§6.2.3 )要求为不同类别的标识符分别命名空间,包括标记标识符 (用于struct / union / enum )和普通标识符 (用于typedef和其他标识符)。

如果你刚才说:

struct Foo { ... };
Foo x;

您会收到编译器错误,因为Foo仅在标记名称空间中定义。

您必须将其声明为:

struct Foo x;

每当你想要引用Foo ,你总是要把它称为struct Foo 。 这会很快烦人,所以你可以添加一个typedef

struct Foo { ... };
typedef struct Foo Foo;

现在struct Foo (在标记命名空间中)和普通Foo (在普通标识符命名空间中)都引用相同的东西,并且您可以在没有struct关键字的情况下自由声明Foo类型的对象。


构造:

typedef struct Foo { ... } Foo;

只是声明和typedef的缩写。


最后,

typedef struct { ... } Foo;

声明一个匿名结构并为其创建一个typedef 。 因此,使用此构造,它在标记名称空间中没有名称,只有typedef名称空间中的名称。 这意味着它也无法向前宣布。 如果要进行前向声明,则必须在标记名称空间中为其指定名称


在C ++中,所有struct / union / enum / class声明都像隐式typedef一样,只要该名称不被另一个具有相同名称的声明隐藏。 有关详细信息,请参阅Michael Burr的答案 。

C ++中''struct''和''typedef struct''之间的区别? - Difference between ''struct'' and ''typedef struct'' in C++?

C ++中''struct''和''typedef struct''之间的区别? - Difference between ''struct'' and ''typedef struct'' in C++?

问题:

In C++, is there any difference between: 在C ++中,之间有什么区别:

struct Foo { ... };

and

typedef struct { ... } Foo;

解决方案:

参考一: https://stackoom.com/question/2ZIG/C-中-struct-和-typedef-struct-之间的区别
参考二: https://oldbug.net/q/2ZIG/Difference-between-struct-and-typedef-struct-in-C

c – ‘struct(*)[]’和’struct * []’之间有什么区别?

c – ‘struct(*)[]’和’struct * []’之间有什么区别?

我正在玩指针,指针数组和数组.

我创建了一个名为Fraction的结构,并尝试将一个Fraction数组传递给一个带有Fraction指针数组的函数.我收到错误:

Error   1   error C2664: 'void display(Fraction *[],int)' : cannot convert 
                             argument 1 from 'Fraction (*)[10]' to 'Fraction *[]'

我知道这不起作用,但你对这些中的每一个都称之为什么?分数(*)[]和分数* [].例如:int []是一个整数数组,int *是一个整数指针.除了围绕*的括号外,上面的代码看起来与我相同.

我不需要修复这个错误我只是想了解这两个看似相似的结构之间的差异.

解决方法

分数* []是分数*(指针数组)的数组.分数(*)[]是指向Fraction [](指向数组的指针)的指针.不同之处在于括号将“指针”与Fraction隔离开,因为否则两者会相互绑定并为您提供与预期不同的类型.

机械地,a *或a&更愿意绑定到一个类型名称而不是被隔离并代表整个事物,所以你必须使用括号将它与元素类型隔离开来.声明函数指针时也是如此:int *(int,int)是一个接受两个int并返回一个int *的函数,而int(*)(int,int)是一个指向一个带两个整数的函数的指针.返回一个int.

考虑this简单程序:

#include <iostream>
#include <typeinfo>

struct Type {};

// 1: Array of Type*.
void func(Type *arr [3]) {
    std::cout << "Type* array.\n"
              << typeid(arr).name() << "\n\n";
}

// 2: Array of Type&.
// Illegal.
// void func(Type &arr [3]) {
//     std::cout << "Type& array.\n"
//               << typeid(arr).name() << "\n\n";
// }

// 3: Pointer to array of Type.
void func(Type (*arr) [3]) {
    std::cout << "Pointer to Type array.\n"
              << typeid(arr).name() << "\n\n";
}

// 4: Reference to array of Type.
void func(Type (&arr) [3]) {
    std::cout << "Reference to Type array.\n"
              << typeid(arr).name() << "\n\n";
}

int main() {
    // Array of Type.
    Type   t_arr[3] = {};

    // Array of Type*.
    Type* tp_arr[3] = { &t_arr[0],&t_arr[1],&t_arr[2] };

    // Array of Type&.
    // Illegal.
    // Type& tr_arr[3] = { t_arr[0],t_arr[1],t_arr[2] };

    std::cout << "Type[3]: " << typeid(t_arr).name() << "\n\n";

    func(t_arr);  // Calls #4.
    func(&t_arr); // Calls #3.
    func(tp_arr); // Calls #1.
}

根据所使用的编译器,它将输出arr的mangled或unmangled类型,输出显示所有三种都是不同的类型:

// MSVC:
Type[3]: struct Type [3]

Reference to Type array.
struct Type [3]

Pointer to Type array.
struct Type (*)[3]

Type* array.
struct Type * *

// GCC:
Type[3]: A3_4Type

Reference to Type array.
A3_4Type

Pointer to Type array.
PA3_4Type

Type* array.
PP4Type

如果你不习惯它,这种语法有点难以理解,并且可能有点容易输入错误,因此如果你需要使用它,建立一个类型别名可能是个好主意.

// Array.
typedef Type Type_arr_t[3];

// Pointer.
typedef Type (*Type_arr_ptr_t)[3];

// Reference.
typedef Type (&Type_arr_ref_t)[3];

// ...

// Without typedefs.
Type   arr   [3];
Type (*arr_p)[3] = &arr;
Type (&arr_r)[3] =  arr;

// With typedefs.
Type_arr_t     arr2;
Type_arr_ptr_t arr2_p = &arr2;
Type_arr_ref_t arr2_r =  arr2;

这在声明返回指针或对数组的引用的函数时非常有用,因为它们看起来很傻而没有typedef,并且很容易出错和/或忘记语法.

typedef Type (*Type_arr_ptr_t)[3];
typedef Type (&Type_arr_ref_t)[3];

// Without typedefs.
Type (*return_ptr())[3];
Type (&return_ref())[3];

// With typedefs.
Type_arr_ptr_t return_ptr_2();
Type_arr_ref_t return_ref_2();

有关如何解析此类内容的更多信息,请参阅clockwise spiral rule.

注意:当数组作为函数参数传递值时,以及在许多其他情况下(特别是在任何不期望数组但指针是的情况下),类型和维度信息都会丢失,并且它是隐式的转换为指向数组第一个元素的指针;这被称为数组decaying into a pointer.这在上面的func(Type * [3])中进行了演示,其中编译器采用Type * [3]的参数类型,Type *的数组,并将其替换为Type **,指向Type *的指针; [3]丢失了,用一个简单的*代替,因为函数可以指针而不是数组.调用func()时,数组会因此而衰减.因此,以下签名被视为相同,参数在所有三个中都是Type **.

void func(Type*[3]);
void func(Type*[] ); // Dimension isn't needed,since it'll be replaced anyways.
void func(Type**  );

这样做是因为它比尝试按值传递整个数组更有效(它只需要传递一个指针,它很容易适合单个寄存器,而不是试图将整个数据加载到内存中),并且因为编码数组键入函数的参数列表将删除函数关于它可以采用的数组大小的任何灵活性(如果函数采用类型[3],那么你不能传递类型[4]或类型[ 2]).因此,编译器将使用Type *静默替换Type [N]或Type [],从而导致数组在传递时衰减.通过专门获取指向数组的指针或引用可以避免这种情况;虽然这与让数组衰减一样有效(前者因为它仍然只传递指针,后者因为大多数编译器使用指针实现引用),但它会失去灵活性(这就是为什么它通常与模板配对,这会恢复灵活性,没有删除任何严格性).

// Will take any pointer to a Type array,and replace N with the number of elements.
// Compiler will generate a distinct version of `func()` for each unique N.
template<size_t N>
void func(Type (*)[N]);

// Will take any reference to a Type array,and replace N with the number of elements.
// Compiler will generate a distinct version of `func()` for each unique N.
template<size_t N>
void func(Type (&)[N]);

但是请注意,C没有丰富的模板,因此任何旨在使用这两种语言的代码都应该使用传递“size”参数和数组的C语言,或者专门为一定大小的数组;前者更灵活,而后者则非常有用,如果您永远不需要采用任何其他大小的数组.

void func1(Type *arr,size_t sz);
void func2(Type (*arr)[3]);

另请注意,有阵列won’t decay into a pointer的情况.

// Example array.
Type arr[3];

// Function parameter.
void func(Type arr[3]);
void func(Type (*arr)[3]);
void func(Type (&arr)[3]);

// Function template parameter.
template<typename T>
void temp(T t);

// Class template parameter.
template<typename T>
struct S { typedef T type; };

// Specialised class template parameter.
template<typename T> struct S2;
template<typename T,size_t Sz>
struct S2<T[Sz]> { typedef T type[Sz]; };

func(arr);           // C: arr decays into Type*.
                     // C++: arr either binds to a Type(&)[3],or decays into Type*.
                     //  If both are available,causes error due to ambiguous function call.
func(&arr);          // C/C++: No decay,&arr is Type(*)[3].
sizeof(arr);         // C/C++: No decay,evaluates to (sizeof(Type) * 3).
alignof(arr);        // C/C++: No decay,evaluates to alignof(Type).
decltype(arr);       // C++: No decay,evaluates to Type[3].
typeid(arr);         // C++: No decay,evaluates to a std::type_info for Type[3].
for (Type& t : arr); // C++: No decay,ranged-based for accepts arrays.
temp(arr);           // C++: arr decays to Type* during function template deduction.
temp<Type[3]>(arr);  // C++: No decay,deduction isn't required.

// For class templates,deduction isn't performed,so array types used as template parameters
//  don't decay.
S<Type[3]>::type;    // C++: No decay,type is Type[3].
S2<Type[3]>::type;   // C++: No decay,type is Type[3].

// String literals are arrays,too.
decltype("Hello.");             // C++: No decay,evaluates to const char[7].
char  c_arr[] = "Hello.";       // C/C++: No decay,c_arr is a local array,of type char[7],//  containing copy of "Hello."
const char* c_ptr   = "Hello."; // C/C++: const char[7] "Hello." is stored in read-only
                                //  memory,and ptr points to it.

// There may be other cases in which arrays don't decay,which I'm currently not aware of.

因此,简而言之,虽然Type [3]是一个数组类型,而Fraction * [5]是一个数组类型,但有些情况下,两个声明将被静默替换为Type *或Fraction **分别由编译器和类型和维度信息将由此丢失;这种损失称为阵列衰减或阵列到指针衰减.

谢谢你去juanchopanza提醒我提到数组到指针的衰变.

我们今天的关于Linux 内核 (x86-64) 程序集,用于将 `struct pt_regs` 解码为系统调用中的寄存器的分享就到这里,谢谢您的阅读,如果想了解更多关于(C) 用 bsearch 在 struct 数组中按名称查找 struct、C ++中''struct''和''typedef struct''之间的区别?、C ++中''struct''和''typedef struct''之间的区别? - Difference between ''struct'' and ''typedef struct'' in C++?、c – ‘struct(*)[]’和’struct * []’之间有什么区别?的相关信息,可以在本站进行搜索。

本文标签: