mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-17 23:07:50 +00:00
The no_mangle attribute is unsafe since Rust 2024
This commit is contained in:
@@ -219,7 +219,7 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
ممکن است متوجه شده باشید که ما تابع `main` را حذف کردیم. دلیل این امر این است که `main` بدون یک رانتایم اساسی که آن را صدا کند معنی ندارد. در عوض، ما در حال بازنویسی نقطه ورود سیستمعامل با تابع `start_` خود هستیم:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -469,7 +469,7 @@ rustflags = ["-C", "link-args=-e __start -static -nostartfiles"]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // don't mangle the name of this function
|
||||
#[unsafe(no_mangle)] // don't mangle the name of this function
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// this function is the entry point, since the linker looks for a function
|
||||
// named `_start` by default
|
||||
|
||||
@@ -216,13 +216,13 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
Vous remarquerez peut-être que nous avons retiré la fonction `main`. La raison est que la présence de cette fonction n'a pas de sens sans un environnement d'exécution sous-jacent qui l'appelle. À la place, nous réécrivons le point d'entrée du système d'exploitation avec notre propre fonction `_start` :
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
En utilisant l'attribut `#[no_mangle]`, nous désactivons la [décoration de nom] pour assurer que le compilateur Rust crée une fonction avec le nom `_start`. Sans cet attribut, le compilateur génèrerait un symbol obscure `_ZN3blog_os4_start7hb173fedf945531caE` pour donner un nom unique à chaque fonction. L'attribut est nécessaire car nous avons besoin d'indiquer le nom de la fonction de point d'entrée à l'éditeur de lien (*linker*) dans l'étape suivante.
|
||||
En utilisant l'attribut `#[unsafe(no_mangle)]`, nous désactivons la [décoration de nom] pour assurer que le compilateur Rust crée une fonction avec le nom `_start`. Sans cet attribut, le compilateur génèrerait un symbol obscure `_ZN3blog_os4_start7hb173fedf945531caE` pour donner un nom unique à chaque fonction. L'attribut est nécessaire car nous avons besoin d'indiquer le nom de la fonction de point d'entrée à l'éditeur de lien (*linker*) dans l'étape suivante.
|
||||
|
||||
Nous devons aussi marquer la fonction avec `extern C` pour indiquer au compilateur qu'il devrait utiliser la [convention de nommage] de C pour cette fonction (au lieu de la convention de nommage de Rust non-spécifiée). Cette fonction se nomme `_start` car c'est le nom par défaut des points d'entrée pour la plupart des systèmes.
|
||||
|
||||
@@ -466,7 +466,7 @@ Un exécutable Rust autoporté minimal ressemble à ceci :
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // ne pas décorer le nom de cette fonction
|
||||
#[unsafe(no_mangle)] // ne pas décorer le nom de cette fonction
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// cette fonction est le point d'entrée, comme le linker cherche une fonction
|
||||
// nomée `_start` par défaut
|
||||
|
||||
@@ -218,13 +218,13 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
`main` 関数を削除したことに気付いたかもしれません。`main` 関数を呼び出す基盤となるランタイムなしには置いていても意味がないからです。代わりに、OS のエントリポイントを独自の `_start` 関数で上書きしていきます:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
Rust コンパイラが `_start` という名前の関数を実際に出力するように、`#[no_mangle]` attributeを用いて[名前修飾][name mangling]を無効にします。この attribute がないと、コンパイラはすべての関数にユニークな名前をつけるために、 `_ZN3blog_os4_start7hb173fedf945531caE` のようなシンボルを生成します。次のステップでエントリポイントとなる関数の名前をリンカに伝えるため、この属性が必要となります。
|
||||
Rust コンパイラが `_start` という名前の関数を実際に出力するように、`#[unsafe(no_mangle)]` attributeを用いて[名前修飾][name mangling]を無効にします。この attribute がないと、コンパイラはすべての関数にユニークな名前をつけるために、 `_ZN3blog_os4_start7hb173fedf945531caE` のようなシンボルを生成します。次のステップでエントリポイントとなる関数の名前をリンカに伝えるため、この属性が必要となります。
|
||||
|
||||
また、(指定されていない Rust の呼び出し規約の代わりに)この関数に [C の呼び出し規約][C calling convention]を使用するようコンパイラに伝えるために、関数を `extern "C"` として定義する必要があります。`_start`という名前をつける理由は、これがほとんどのシステムのデフォルトのエントリポイント名だからです。
|
||||
|
||||
@@ -473,7 +473,7 @@ rustflags = ["-C", "link-args=-e __start -static -nostartfiles"]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // この関数の名前修飾をしない
|
||||
#[unsafe(no_mangle)] // この関数の名前修飾をしない
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// リンカはデフォルトで `_start` という名前の関数を探すので、
|
||||
// この関数がエントリポイントとなる
|
||||
|
||||
@@ -234,13 +234,13 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
우리는 운영체제가 호출하는 프로그램 실행 시작 지점 대신 우리의 새로운 `_start` 함수를 실행 시작 지점으로 대체할 것입니다.
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
`#[no_mangle]` 속성을 통해 [name mangling]을 해제하여 Rust 컴파일러가 `_start` 라는 이름 그대로 함수를 만들도록 합니다. 이 속성이 없다면, 컴파일러가 각 함수의 이름을 고유하게 만드는 과정에서 이 함수의 실제 이름을 `_ZN3blog_os4_start7hb173fedf945531caE` 라는 이상한 이름으로 바꿔 생성합니다. 우리가 원하는 실제 시작 지점 함수의 이름을 정확히 알고 있어야 링커 (linker)에도 그 이름을 정확히 전달할 수 있기에 (후속 단계에서 진행) `#[no_mangle]` 속성이 필요합니다.
|
||||
`#[unsafe(no_mangle)]` 속성을 통해 [name mangling]을 해제하여 Rust 컴파일러가 `_start` 라는 이름 그대로 함수를 만들도록 합니다. 이 속성이 없다면, 컴파일러가 각 함수의 이름을 고유하게 만드는 과정에서 이 함수의 실제 이름을 `_ZN3blog_os4_start7hb173fedf945531caE` 라는 이상한 이름으로 바꿔 생성합니다. 우리가 원하는 실제 시작 지점 함수의 이름을 정확히 알고 있어야 링커 (linker)에도 그 이름을 정확히 전달할 수 있기에 (후속 단계에서 진행) `#[unsafe(no_mangle)]` 속성이 필요합니다.
|
||||
|
||||
또한 우리는 이 함수에 `extern "C"`라는 표시를 추가하여 이 함수가 Rust 함수 호출 규약 대신에 [C 함수 호출 규약][C calling convention]을 사용하도록 합니다. 함수의 이름을 `_start`로 지정한 이유는 그저 런타임 시스템들의 실행 시작 함수 이름이 대부분 `_start`이기 때문입니다.
|
||||
|
||||
@@ -487,7 +487,7 @@ Linux, Windows 또는 macOS 위에서 동작하는 freestanding 실행파일을
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // 이 함수의 이름을 mangle하지 않습니다
|
||||
#[unsafe(no_mangle)] // 이 함수의 이름을 mangle하지 않습니다
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// 링커는 기본적으로 '_start' 라는 이름을 가진 함수를 실행 시작 지점으로 삼기에,
|
||||
// 이 함수는 실행 시작 지점이 됩니다
|
||||
|
||||
@@ -213,13 +213,13 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
You might notice that we removed the `main` function. The reason is that a `main` doesn't make sense without an underlying runtime that calls it. Instead, we are now overwriting the operating system entry point with our own `_start` function:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
By using the `#[no_mangle]` attribute, we disable [name mangling] to ensure that the Rust compiler really outputs a function with the name `_start`. Without the attribute, the compiler would generate some cryptic `_ZN3blog_os4_start7hb173fedf945531caE` symbol to give every function a unique name. The attribute is required because we need to tell the name of the entry point function to the linker in the next step.
|
||||
By using the `#[unsafe(no_mangle)]` attribute, we disable [name mangling] to ensure that the Rust compiler really outputs a function with the name `_start`. Without the attribute, the compiler would generate some cryptic `_ZN3blog_os4_start7hb173fedf945531caE` symbol to give every function a unique name. The attribute is required because we need to tell the name of the entry point function to the linker in the next step.
|
||||
|
||||
We also have to mark the function as `extern "C"` to tell the compiler that it should use the [C calling convention] for this function (instead of the unspecified Rust calling convention). The reason for naming the function `_start` is that this is the default entry point name for most systems.
|
||||
|
||||
@@ -463,7 +463,7 @@ A minimal freestanding Rust binary looks like this:
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // don't mangle the name of this function
|
||||
#[unsafe(no_mangle)] // don't mangle the name of this function
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// this function is the entry point, since the linker looks for a function
|
||||
// named `_start` by default
|
||||
|
||||
@@ -216,13 +216,13 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
Можно заметить, что мы удалили функцию `main`. Причина в том, что `main` не имеет смысла без стандартного runtime, которая ее вызывает. Вместо этого мы переопределим точку входа операционной системы с помощью нашей собственной функции `_start`:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
Используя атрибут `#[no_mangle]`, мы отключаем [искажение имен][name mangling], чтобы гарантировать, что компилятор Rust сгенерирует функцию с именем `_start`. Без этого атрибута компилятор генерировал бы какой-нибудь загадочный символ `_ZN3blog_os4_start7hb173fedf945531caE`, чтобы дать каждой функции уникальное имя. Атрибут необходим, потому что на следующем этапе нам нужно сообщить имя функции точки входа компоновщику.
|
||||
Используя атрибут `#[unsafe(no_mangle)]`, мы отключаем [искажение имен][name mangling], чтобы гарантировать, что компилятор Rust сгенерирует функцию с именем `_start`. Без этого атрибута компилятор генерировал бы какой-нибудь загадочный символ `_ZN3blog_os4_start7hb173fedf945531caE`, чтобы дать каждой функции уникальное имя. Атрибут необходим, потому что на следующем этапе нам нужно сообщить имя функции точки входа компоновщику.
|
||||
|
||||
Мы также должны пометить функцию как `extern "C"`, чтобы указать компилятору, что он должен использовать [соглашение о вызове C][C calling convention] для этой функции (вместо неопределенного соглашения о вызове Rust). Причина именования функции `_start` в том, что это имя точки входа по умолчанию для большинства систем.
|
||||
|
||||
@@ -465,7 +465,7 @@ rustflags = ["-C", "link-args=-e __start -static -nostartfiles"]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // don't mangle the name of this function
|
||||
#[unsafe(no_mangle)] // don't mangle the name of this function
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// this function is the entry point, since the linker looks for a function
|
||||
// named `_start` by default
|
||||
|
||||
@@ -184,7 +184,7 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
读者也许会注意到,我们移除了 `main` 函数。原因很显然,既然没有底层运行时调用它,`main` 函数也失去了存在的必要性。为了重写操作系统的入口点,我们转而编写一个 `_start` 函数:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -422,7 +422,7 @@ rustflags = ["-C", "link-args=-e __start -static -nostartfiles"]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // 不重整函数名
|
||||
#[unsafe(no_mangle)] // 不重整函数名
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// 因为链接器会寻找一个名为 `_start` 的函数,所以这个函数就是入口点
|
||||
// 默认命名为 `_start`
|
||||
|
||||
@@ -216,7 +216,7 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
您可能會注意到我們移除了 `main` 函式,原因是因為既然沒有了底層的執行時系統呼叫,那麼 `main` 也沒必要存在。我們要重寫作業系統的入口點,定義為 `_start` 函式:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -465,7 +465,7 @@ rustflags = ["-C", "link-args=-e __start -static -nostartfiles"]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle] // 不修飾函式名稱
|
||||
#[unsafe(no_mangle)] // 不修飾函式名稱
|
||||
pub extern "C" fn _start() -> ! {
|
||||
// 因為連結器預設會尋找 `_start` 函式名稱
|
||||
// 所以這個函式就是入口點
|
||||
|
||||
Reference in New Issue
Block a user