質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Q&A

5回答

791閲覧

gcc fpie どこからプログラムがメモリにマップされた場合でも正しくある関数のアドレスをメモリに格納したい

kazuyakazuya

総合スコア193

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

0グッド

2クリップ

投稿2020/11/15 13:17

編集2020/11/19 10:29

自作OS

gcc -c -O0 -fPIE -m32 -mgeneral-regs-only プログラム名.c

objcopy --only-section=.text --output-target binary プログラム名.o filebin

これでRAWバイナリにして実行しています。

gccのコンパイル時に-fpieオプションを付ければ"位置独立コード"を生成できるようです。
どこのアドレスから展開しても問題なく動かせるってことですね

では、・・・

sample_function(){} main(){ int * p = 0x00000000; void (*func_p)() = sample_function; //32bit環境を想定 int dummy = func_p; *p = dummy; }

(コード正しいかわからないけど・・・)
メモリアドレス0x00000000にsample_function関数のアドレスを格納するプログラムです。

で、質問なのですが 
どこのアドレスにマップされた場合でも
0x0000000に正しくsample_function関数のアドレスが格納されるのでしょうか?

仮に正しく格納されないとして
正しく格納させる方法とかはないでしょうか?

質問内容おかしかったらすみません
わからないのでお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuma-s

2020/11/18 13:20

> gccのコンパイル時に-fpieオプションを付ければ"位置独立コード"を生成できるようです。 -fpic または -fPIC のことでしょうか? (position independent code) -fpie があるのなら、その説明のある URL を示してください。
rubato6809

2020/11/19 09:37

0. 自作OS上でのことだというなら、その条件を問題に含めてください。 自作OSとなると、それがどの程度動いているか、そっちの問題じゃないのかと思ってしまうので、 1. 「0番地に、関数アドレスを書く」プログラムですが、そのような制約が無いプログラムなら動作するのですか。とにかくなんでも良いので、コンパイルしたコードが動作することを確認できているのか、ということです。 2.0番地に(アドレスではなく)普通の整数値なら書けてますか。 3.よりによって0番地に書く理由・目的は何ですか。 4.-fpie 位置独立実行形式でなければならない理由・目的は何ですか。 割込みベクタをセットするためであれば位置独立コードは必須条件ではないです。それとも割込みハンドラが何番地に配置されるか、リンク時に決まらない=実行時でないとアドレスが決まらない、という事情がありますか。 以上に対する答えも問題文に追加すれば結構。
kazuyakazuya

2020/11/19 10:25

[0] 追記いたします [1] 動いているのかさえ不明です。 [2] そのままの意味ですか? それなら書けています。(なので、関数の配置アドレスを固定すれば 任意のアドレスにその関数のアドレスを格納するってのはできるが 柔軟性がないからやりたくない。) [3] 特に理由はありません。 X86プロテクトモードなら0x0000番地は勝手に使ってもいい(・・・はず) [4] 前提として ブートローダーをアセンブリ(NASM)で、 カーネルをcで書いています。 両者のリンクのさせかたがわからないので苦肉の策として、 cで書かれたカーネルをオブジェクトファイルに変更したあとOBJCOPYで RAWバイナリにし、 それをブートローダーにくっつけることで ブートローダーとカーネルを繋いでいます。 -fpie指定しないで上記の手順でRAWバイナリを生成した場合コードがうまく動きません。 https://teratail.com/questions/302484 >リンク時に決まらない=実行時でないとアドレスが決まらない、という事情がありますか。 リンクしていません。(ライブラリは使っていない) ただ、どこのメモリアドレスからこのプログラムを配置するかは決まっています。 (-FPIEオプションをつけずにオブジェクトファイルを生成し そこからRAWバイナリ形式に変換した場合 そのプログラムはどこのアドレスから動くことを前提に作られているのか全くわからない。 だから、とりあえずどこでも動くように-FPIEオプションをつけています。)
rubato6809

2020/11/19 10:38

以上の状況を整理して、このスレッドに書くのではなく、質問文に追加してください。
rubato6809

2020/11/19 11:25

> 動いているのかさえ不明です これは質問の意図を誤解されたかな。だってyoutubeにアップした動画は「ともかく何かは動いている」んでしょ。
kazuyakazuya

2020/11/19 11:30

すみません まず、"そのような制約"とは何のことですか?
rubato6809

2020/11/19 11:34

そのような制約とは「0番地に、関数アドレスを書く事」という意味でかきました。 ともかく動いているか?という問いです。
kazuyakazuya

2020/11/19 11:54 編集

割り込み設定の中で IDTに割り込みハンドラのアドレスを格納する必要があります。 で、そのIDTの開始アドレスが0番地です。 ”0番地に、関数アドレスを書く事”をしないと割り込み設定ができないです。 (フォーマット的に正確にはそのまま0番地に書き込むわけではないけど)
guest

回答5

0

根本的解決ではありませんのでまだ"解決"にはしません。
でもこれで一応関数ポインタとして機能するでしょう

void function(void); void sample(void){ void (*p)() = function; } void function(void){}

これをコンパイルすると(一部のみ記載)
gcc -S -O0 project2.c

movl $_function, -4(%ebp)

さらに機械語に直すと
gcc -c -O0 project2.c
objcopy --only-section=.text --output-target binary project2.o filebin

55 89 E5 83 EC 10 C7 45 FC 1A 00 00 00 90 90 90 90 90 90 90 90 90 90 90 C9 C3 55 89 E5 90 5D C3

intelマニュアル

movl $_function, -4(%ebp)

これに対応するのが
C7 45 FC 1A
これですね。(機械語できるわけではないから詳しいことはわからない)

で、このなかの0x1Aが上記のアセンブリで言うところの$_functionです。

で、このrawバイナリのオフセット0x1A番目にfuncion関数が存在します。

つまり、関数ポインタを使うことができないかったのは

その関数ポインタが指していたのは

生成されたrawバイナリの中での関数のオフセットを指していたからです。

だから関数ポインタだけ使えなかったようです。

なので・・・

void (*p)(void *) = Handler_List_0x00;

    p = p + rawバイナリがロードされるアドレス;

とやったところ無事動作しました。

投稿2020/11/21 07:25

編集2020/11/21 07:30
kazuyakazuya

総合スコア193

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rubato6809

2020/11/22 11:14

>これをコンパイルすると(一部のみ記載) >gcc -S -O0 project2.c とすると >movl $_function, -4(%ebp) この時、-fPIE 又は -fPIC オプションを指定しても同じ命令になりましたか?
kazuyakazuya

2020/11/22 11:27

今確認しましたが全く同じ結果になりました。
rubato6809

2020/11/22 11:37

位置独立実行形式であれば実行時に関数アドレスを計算する違う命令を使う可能性があるのですが、オプションを指定しても同じなら仕方ないのでしょう。 $_function はアセンブルした時点の、関数のリロケータブルアドレスです。通常はリンカ(とローダ)がしかるべきアドレス値に直してくれるのです。 リンカ(とローダ)を使わない代りに p = p + rawバイナリがロードされるアドレス; とする、というわけです。
kazuyakazuya

2020/11/22 11:51 編集

呼び出す関数 自分の回答で言ううところのfunction関数を定義しないまま gcc -c -O0 project2.c objcopy --only-section=.text --output-target binary project2.o filebin とやると C7 45 FC 00 00 00 となっていました。 これもリンクさせればリンカが適切に書き換えてくれるのですね。 gcc -c -O0 project2.c objcopy --only-section=.text --output-target binary project2.o filebin >通常はリンカ(とローダ)がしかるべきアドレス値に直してくれるのです。 オブジェクトファイルの段階では関数ポインタは そのファイル内(.textセクションでの)での関数オフセットが設置され リンクの段階でさらにロードアドレス分加算される・・・なら リンクの際、リンカスクリプトでプログラムのエントリアドレスを指定できれば 関数ポインタも使えるようになったりしないのでしょうか? p = p + リンカスクリプトで指定したエントリアドレス;
rubato6809

2020/11/23 00:18

リンカ使えば、fpie 関係なく関数ポインタも使えますよ。それが組込みでも、自作osでも、普通のやりかたじゃないですか。
kazuyakazuya

2020/11/23 11:50

うーん、例えば組み込みではどのようにリンクさせているのですか? 何もオプションで指定しないでリンクしたら"実行形式ファイル"が生成されますよね。 もちろん 自作OSや組み込みだとそのまんまメモリにマップしたら動かないわけですが どうやって実行形式ファイルからrawバイナリへ変換しているんですか?
rubato6809

2020/11/24 00:49

> 例えば組み込みではどのようにリンクさせているのですか? それ自体が新たな質問じゃないだろうか。こういうところでは質問のポイントを絞らないと。 それに、まず自分で調べるのが先決。 > 何もオプションで指定しないでリンクしたら"実行形式ファイル"が生成 それは cc にオプション指定しないでコンパイルすることを言ってますか?リンカスクリプトという言葉は知ってても、誤解があるのでは。 *.o ファイルまでコンパイルした後、複数の*.o ファイルとライブラリをまとめて、実行形式を作るのがリンカでしょ、GNUツールだとld。その ld にリンクの仕方を指定するのがリンカスクリプト 詳細はともかく、実行形式も目的のメモリマップも ld に対してリンカスクリプトを含めた指定をする(cc はデフォルトのリンカスクリプトを使う)んじゃないのかしら・・・そういう私は統合開発環境で組込開発した際にリンカスクリプトに相当するものを編集したことはあるが、リンカスクリプトそのものをいじった経験はないので具体的な指南はできない。悪しからず。
rubato6809

2020/11/24 06:30 編集

objcopy は .data(=初期値つき変数)もスタックも「取り出し」ていないと思います。それでも規模の小さなプログラムなら動作する可能性はあります。 要するにこれらのセクションは最低限、RAMメモリが物理的に存在しさえすれば良い。必要なのは .text の機械語コードがアクセスする番地のメモリです。 そもそもスタック領域は、プログラム起動時にメモリ内容を初期化する必要はありません。グローバル変数なども、初期値を期待しないコードばかりなら、これも初期化は不要です。それだけのことではないでしょうか。 ライブラリ関数の中には内部に初期値付き変数(staticなテーブルなど?)を持ってるものがあるので、それを使ったらアウトじゃないですかね。
rubato6809

2020/11/24 06:25

(あれ?コメントが削除されていた)
kazuyakazuya

2020/11/24 08:55

すみません もうちょっと考えてから返信しようと消してしまいました。 となりますと、 今まで私のプログラムが動いていたのは偶然、すべて.textに配置されていたからであり static変数などを使うと動かなくなる・・・と これは大問題なのでリンクのさせかたを考えます・・・ ありがとうございました
kazuyakazuya

2020/11/24 10:29 編集

あ、もうひとつ聞くの忘れてた もう少し付き合ってくれると助かります。 >リンカ使えば、fpie 関係なく関数ポインタも使えますよ。それが組込みでも、自作osでも、普通のやりかたじゃないですか。 リンクする時点で オブジェクトファイルの各セクションがどこのアドレスから配置されるということを前提にリンクされるものだと思われますが -fpieオプションをつかってコンパイルしたプログラムの場合 アドレスを計算してくれるプログラムを付属されるのですか? それとも、それとも全部相対アドレスを使うようになるとかでしょうか? (そういえば-fpieオプションをつけた場合 プログラムの各セクションをメモリ上どこに配置しても問題なく動く・・・?)
rubato6809

2020/11/25 00:03

私は「全部相対アドレスを使う」位置独立コードを使った経験があって、以前そのようなコードをGCCも生成するのを見たように思っていたのですが、 「movl $_function, ???」形式の命令しか出ないとすると、あれ?という感じです。私自身、優先度低く調査中。
guest

0

0x0000000に正しくsample_function関数のアドレスが格納されるのでしょうか?

そのコードは、関数アドレスを0番地に格納しようとするでしょう。格納できてもおかしくないです。
質問者は「0番地に書かれた/書かれていない」ことを判定できてない状態じゃないですか。

割り込み設定ができない

割込みが使えない、その原因はただ一つ、0番地にアドレスを書けてないからだ・・・と考えているなら、ちょっと待ってほしい。割込みがちゃんと使えるには、ほかにもいろいろな条件をクリアしないといけませんよ。私は具体的に指摘できるほどの知識は無いけど、原因を特定できる状態ではないんじゃないかな。

gcc -c -O0 -fPIE -m32 -mgeneral-regs-only プログラム名.c objcopy --only-section=.text --output-target binary プログラム名.o filebin

なるほどね。リンクせず、ソースコードをアセンブルしただけで機械語を動かそうとしている、とでもいえばよいのかしら。この場合、-PIE 又は -fPIC は必須な条件であるようですね。
「関数を新たに定義すると動かなくなる」・・・拝見しました。それが-fPIEで関数を呼び出せるようになったということは、-fPIEが無い場合は関数呼出しの call 命令のオペランドがリンカによって決定される、そのような命令にコンパイルされている、ことを示しています。
一方、-fPIE はアセンブルした時点で関数呼出し の call 命令がそのまま動作可能な機械語になるんですね。call 命令の形式はひとつじゃなくて、飛び先を指定する方法が違うので。

リンクしない、つまり分割コンパイルは不可能、ソースコード一本プログラムしか動かせない。その程度のコードをOSと呼ぶのはまだまだ早い。OSを自作したくてよちよち歩きを始めたところならそうした事情・条件を、最初から詳しく示して問うべきだったでしょう。
アセンブラ、リンカなどのツールの使い方、その意味。カギになる機械語(例えばcall命令)の動作、CPUのアーキテクチャ諸々、ハードウェアの具体的な事情の数々・・・まだまだ先は長そうですね。Enjoy!

投稿2020/11/19 12:39

編集2020/11/19 12:48
rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rubato6809

2020/11/19 12:53

画面に表示できるなら独自のデバッグ環境を作れそうですけどね。
kazuyakazuya

2020/11/19 13:31

>割込みが使えない、その原因はただ一つ、0番地にアドレスを書けてないからだ・・・と考えているなら、ちょっと待ってほしい。 一応正しいアドレスを書き込めていないという根拠はあります。 割り込みハンドラ登録関数を作成しました。(Linuxのぱくっただけだけど) この関数は正しく動作します void * p; __asm__ __volatile__( "MOV %%DX,%%AX\n\t" "MOV %%EAX,%0\n\t" "MOV %2,%%DX\n\t" "MOV %%EDX,%1\n\t" :"=m" (*IDT_Address_Low),"=m" (*IDT_Address_High) :"i" ((short)(0x8000 + (0 << 13) + (0b110 << 8))),"a" ((Selector)<<16),"d" (p) ); void型変数pに割り込みハンドラのアドレスを格納します。 void (*p)(void *) = Handler_List_0x00; と関数ポインタを入れてから割り込みを起こすと暴走します。 割り込みハンドラの処理が行われずに暴走するので 割り込みハンドラアドレスが正しく設定されていない思われます。 一応、割り込みハンドラがどこのアドレスに配置されるかは確認しているので void * p = 0xF41C; //ハンドラアドレスを格納 のようにやってやると問題なく割り込みハンドラが呼び出されます。 なので、関数ポインタに適切な値が入っていないものだと思っています。 う~ん、-fpieでjmpやcallする際は相対アドレスが使われるようになっているんですかね・・・? ポインタとかってどうなのでしょうか? 仕組み的にポインタが使えないような気がしてきましたが・・・ >リンクしない、つまり分割コンパイルは不可能、ソースコード一本プログラムしか動かせない。 やっぱ、この方法だと限界が近そうですね・・・
kazuyakazuya

2020/11/19 13:32

>画面に表示できるなら独自のデバッグ環境を作れそうですけどね。 レジスタの値を表示する ある時点での変数の値を表示する メモリの内容を表示する ならたぶん 作れます。
rubato6809

2020/11/19 14:02

メモリ内容を表示できるなら格納した値が正しいかどうかわかる。書けてるけど書いた値が違っているなら関数アドレスの計算が間違いということになる・・・ ひとつひとつ直接証拠を取ることをお勧めします。
guest

0

一般的なC言語の機能のみでは不可能です。これを実現できる可能性があるのは以下の場合に限ります。

OSのAPIを使えばできるかもしれません。

まあ、他の人の対話を見る限り、これは目的ではなさそうですね。

自力でOSごと作るとか、特殊な環境下ならばできるかもしれません。

この場合ならできるかもしれません。まあ、この場合ならばそもそもC言語使う意味が薄いです(アセンブラなり機械語なりで作ると考える)。

投稿2020/11/18 11:51

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuyakazuya

2020/11/18 12:45

質問文に環境を書いておりませんでした。 コンパイルしたものをrawバイナリ形式に直しVM上で動かしています。 つまり自作osですね。 rawバイナリ・・・メモリに本当にそのまんまマップすれば動くプログラムという意味で使っています >この場合ならできるかもしれません。まあ、この場合ならばそもそもC言語使う意味が薄いです(アセンブラなり機械語なりで作ると考える)。 アセンブリでならできましたが、C言語(質問文のコード)ではできませんでした。
HogeAnimalLover

2020/11/18 13:52 編集

OSが独自ならばコンパイラもそれに併せなければいけません。gccでそれに対応することを期待するのは無理があります。
kazuyakazuya

2020/11/18 13:51

いいえ。 ライブラリは一切使ってないので大丈夫・・・という認識なのですが他に必要な理由があるのですか?
kazuyakazuya

2020/11/18 14:20

>gccでそれに対応することを期待するのは無理があります。 otnさんにも同じ内容を聞きましたが リンカスクリプトを使ってエントリポイントを指定できれば ”どこからプログラムがメモリにマップされた場合でも正しくある関数のアドレスをメモリに格納する"というのはできるのでしょうか?
guest

0

0x0000000に正しくsample_function関数のアドレスが格納されるのでしょうか?

多分、出来るでしょう。
ただし、大抵の場合、実行時エラーとなります。(特に、Windows等のOSが管理するシステムの場合)
そのアドレスがそのアプリで書き込みが許可されないため。
また、仮想記憶となっている事が大半のため、メモリ上のアドレスには一致しません。

なお、組み込み系などで、仮想記憶か使われてなく、指定アドレスが実在する場合は、書き込みはOKですね。

投稿2020/11/18 11:37

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuyakazuya

2020/11/18 12:42

質問文に環境を書いておりませんでした。 コンパイルしたものをrawバイナリ形式に直しVM上で動かしています。 つまり自作osですね。 rawバイナリ・・・メモリに本当にそのまんまマップすれば動くプログラムという意味で使っています >なお、組み込み系などで、仮想記憶か使われてなく、指定アドレスが実在する場合は、書き込みはOKですね。 実際やってみたのですが 正しい関数のアドレスをメモリに格納できていませんでした。
pepperleaf

2020/11/18 23:13

今のOSだとちゃんとマップしない(リンカで設定)と無理なんでしょうね。 役に立たない回答で申し訳ないです。 昔、ROMに展開したCだと、諸般の事情で、時折、書いてました。
rubato6809

2020/11/19 12:38

> 実際やってみたのですが > 正しい関数のアドレスをメモリに格納できていませんでした それを、どうやって判断したのですか。
pepperleaf

2020/11/20 00:04

そうですね、どうやって確認したかが問題。 一般的な(今時の)OSなら、書き込みできなかったら、例外とかあるけど、OSがないとか、あってもメモリ管理とかしてないと、書き込み失敗してもエラーにもならない事があります、書き込みがブラックホールに飲み込まれた可能性は? あと、gccあたり(だけでもないけど)だと、アセンブラ出力があると思うので、そちらで確認すべき。
kazuyakazuya

2020/11/20 11:45 編集

int型変数の中身を表示する関数を作りました。 Handler_List_0x00関数(割り込みハンドラ)はメモリ0xF41Cに配置されます。 これはバイナリエディタで関数設置位置を確認しました。 (メモリロード位置 + バイナリ上の関数位置) void (*p)(void *) = Handler_List_0x00; 関数ポインタpの値を画面に表示させたところ 0xF41Cではなく0x001Cと出たので 関数ポインタに適切な値が入っていないのは確実だと思います。
kazuyakazuya

2020/11/20 11:43

その0xF41Cに設置されるのはそもそも正しいのか?に関しては 0xF41Cを割り込みハンドラ開始アドレスとして IDTに登録すると その関数が割り込み時呼び出されるので合っているはずです。
kazuyakazuya

2020/11/20 16:24

>あと、gccあたり(だけでもないけど)だと、アセンブラ出力があると思うので、そちらで確認すべき。 アセンブリレベルでは具体的にどんな数値のアドレスをメモリに格納しているのかというのは確かめようがない気がしますが 私の間違いでしょうか? 例えば・・・ int dummy1 = 1; int *dummy1_p = &dummy1; movl $1, 8(%esp) leal 8(%esp), %eax movl %eax, 12(%esp) esp + 8 のアドレスがint型変数dummy1の領域。 movl $1, 8(%esp) dummy1の領域に数値1を格納。 esp + 12で表される場所がint型ポインタの領域。 leal 8(%esp), %eax eaxに8(%esp)つまりdummy変数の領域のアドレスを格納。 最後にこれでポインタ領域(esp + 12)にdummy変数のアドレスを格納。 movl %eax, 12(%esp) 見ての通り具体的なポインタの数値はわからない。
guest

0

論理メモリの「とある番地」にプログラムを配置するのはローダー(リンカー)の機能です。
Cプログラムの記述で、特定の番地にプログラムを配置することは出来ません。

投稿2020/11/18 10:18

otn

総合スコア84491

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuyakazuya

2020/11/18 10:27

すみません 自作OSなど プログラムを任意の位置にマップできるような環境においての話です。
otn

2020/11/18 10:30

Cコンパイラも自作ですか?
otn

2020/11/18 11:02 編集

では、 > Cプログラムの記述で、特定の番地にプログラムを配置することは出来ません。 ということになります。 そういう事ができるように、Cを拡張するのは可能だと思いますが、そういう拡張版のC処理系が存在するかどうかは知りません。
kazuyakazuya

2020/11/18 11:06

生成した実行ファイルなりオブジェクトファイルからrawバイナリ形式で取り出し、 そのrawバイナリ形式のプログラムを任意のメモリにマップするようなプログラム(ブートローダー) を作成すればいい話のように思いますが・・・? rawバイナリ・・・メモリにそのまんまマップするだけで動く形式 どこのメモリからマップしても動いてくれるように コンパイル時に -fPIEオプションをつけています。
otn

2020/11/18 11:10

お書きのように、ローダーを自作するのはもちろん可能です。 「出来ない」と書いたのは、質問文のようなコードのことです。
kazuyakazuya

2020/11/18 11:13

そうでしたか すみません。 ちなみに、質問文のようなコードはリンカスクリプトでプログラムのエントリポイントを指定した場合でも無理ですか?
otn

2020/11/18 11:29

「ような」の表す物が分かりませんが、普通に書かれたCプログラムを対象に、その中の1つの関数名を指定してその関数の配置論理アドレスをオプションで指定するようなリンカー(ローダー)を作るのはもちろん可能だと思います。 あるとすると、仮想記憶が無いような組み込み系ですかね。手動でオーバーレイするようなケース。
kazuyakazuya

2020/11/19 08:03 編集

実現したいこと: 関数のアドレスをメモリに配置する。 自作osの割り込み設定を行っており、正しい割り込みハンドラ設置アドレスを あるメモリ位置に格納する必要があります。 (割り込みハンドラのアドレスを固定する手もあるが柔軟性がなくなるから避けたい) また、私のosではページングは無効化されているので 仮想アドレスのことはあまり気にしなくていい気がします。 (セグメントに関してはメモリ全体を指すようにしている。) >普通に書かれたCプログラムを対象に、その中の1つの関数名を指定してその関数の配置論理アドレスをオプションで指定するようなリンカー(ローダー)を作るのはもちろん可能だと思います。 私の認識に誤りがあるかもしれませんが。。。 自分でリンカやコンパイラを作らずとも gccでコンパイルした後、リンクスクリプトを使ってリンクさせれば そのプログラムがどこのアドレスから置かれて スタートするのかを決めることができ、 どこのアドレスから開始するかわかるってことは 関数の配置アドレスもわかるから "関数のアドレスをメモリに配置する" のも可能なじゃないかと考えているのですがこれって違うのですか?
otn

2020/11/19 10:08

すみませんが、文章の意味がわかりません。 「とある関数を自分の指定したアドレスに配置したい」 じゃなくて 「とある関数がどのアドレスに配置されるかを知りたい」 ということだったのでしょうか?
otn

2020/11/19 10:17

>普通に書かれたCプログラムを対象に、その中の1つの関数名を指定してその関数の配置論理アドレスをオプションで指定するようなリンカー(ローダー)を作るのはもちろん可能だと思います。 以上に言うことは無いです。
dodox86

2020/11/19 10:39

>@kazuyakazuyaさん > gccでコンパイルした後、リンクスクリプトを使ってリンクさせれば > そのプログラムがどこのアドレスから置かれて > スタートするのかを決めることができ、 言葉が足りないだけかもしれませんが、「プログラムがどこから置かれて」の部分は認識が違うかもしれません。その部分に置くのはOSがあれば実行ファイルのローダーであり、OSが無ければプログラマーが配置します。リンカースクリプトが指定可能なのはあくまでオブジェクトコードに書かれるジャンプ、コールなどに関連する絶対番地の値です。その辺りの認識は合っていますでしょうか。そのプログラムは指定のメモリ番地に配置された前提で動き始めるだけです。
kazuyakazuya

2020/11/19 11:33 編集

"置かれて"ってのは余計でしたね すみません。 >リンカースクリプトが指定可能なのはあくまでオブジェクトコードに書かれるジャンプ、コールなどに関連する絶対番地の値です。 ポインタ類の値はリンカスクリプトの内容によって左右されないのですか? >その辺りの認識は合っていますでしょうか。 理解できていないと思います
kazuyakazuya

2020/12/09 19:58

すみません なんでもないです。 ローカルで宣言された自動変数の領域はすべてスタックに確保されるのだからそうですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問