
C言語で書いてコンパイルしたプログラムで、実行中に関数のバイトコードのサイズを調べる手段はありますか?今、鋳型となる関数を用意して、それを別のメモリ上にコピーして実行させることを考えています。そのとき、関数をコピーするために関数のメモリ上でのサイズが必要です。OSはUbuntuを使っており、コンパイラはgccです。可能なら他の環境でも動く方法が知りたいです。
シンボルテーブルを解析する方法はどうかと思い調べたのですが、情報が乏しくnmコマンドの使い方程度しか見つかりませんでした。なにかいい方法をご存知でしたら力をお貸しいただけると幸いです。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
質問者さんの今の状況は、四則演算も理解していないのに「数学に興味を持ったので、テンソル解析の問題を解いてみたいと思っています。
xxすれば解けるのではないかと思っていますが、Σという記号の意味が分かりません。なんでもよいからヒントを教えてください」と言っているようなものです。回答している皆さんはどれだけ的外れな質問をされているかは理解した上でご回答されていると思いますが、まず質問者さんご自身が基礎知識を身につけなければハナシになりません。まずフツーにプログラム言語を「利用」できるレベルになって、それから簡単なインタプリタが実装できる程度の知識は身につけましょう。並列計算の「実験」はその後のハナシです。
ご指摘ありがとうございます。
Wr5さん、Tacosanさんに大変なご迷惑をおかけしました。身の程知らずにも不躾な物言いをしたことをお詫びいたします。
基礎知識を学び直した上で出直します。皆様、貴重な時間を割いてお付き合いくださりありがとうございました。
No.4
- 回答日時:
>並列計算に興味を持ち、複数のスレッドが干渉し合わないようにスレッドの数だけ関数をコピーして分離する方法、として実験してみようと考えました。
グローバル変数なり使っていなければ普通は他のスレッドへの悪影響とかは出ませんよ?
ローカル変数なら一般的にスタック上に作成されますし、スレッド毎に別々のスタックが用意されるはずです。
むしろ…CPUの1次/2次キャッシュの恩恵が受けられなくなる分、性能が低下しそうではありますが……。
# 最近のCPUなら3次キャッシュくらいまでありますかね。
>並列化の方法のニュアンスが違うようなので、可能なところまで自作してみようと思っています。
そういうレベルでの車輪の再発明はしないですね。私なら…。
演算効率とか極限まで求めるのであれば、ソレ系統な大学や研究室でやるべきかと思いますし。
ご回答ありがとうございます。
>スレッド毎に別々のスタックが用意されるはずです。
そうだったのですか!ローカル変数についての知識が曖昧でした。勉強になります。
可能かどうかの実験をしてみたいだけで、極めてライブラリを作ろうとまでは考えていません・・・性能の低下も現行は意識していません。
最初の「関数のメモリ上でのサイズを知る方法」という質問から次第に遠ざかっている気がするので、新しい質問の補足をお読みいただいた上で、回答に補足をいただけるようであればよろしくお願いします。
No.3
- 回答日時:
多分「C言語でやろうとするとやはりアセンブリ言語やアーキテクチャに関する知識は不可欠になってしまいますかね・・・」は誤解だと思います. おそらく
「C言語でやろうとなにでやろうとやはりアセンブリ言語やアーキテクチャに関する知識は不可欠になってしまいますかね・・・」
の方が適切ではないかと. もしそうじゃなくって「他の言語でやれば簡単」ということなら, その「他の言語」を使うことを最初に考えるでしょうし.
ところで「複数のスレッドが干渉し合わないように」ってのがわからないんですけど, 具体的にはどのような状態が「干渉している」ということになるんでしょうか?
以下, ちょっと手元の gcc 4.8.2 (windows) で遊んでみました.
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
をコンパイルしてできるアセンブリソースを見ると "hello world\n" を RIP 相対アドレスで扱ってますから, 「単純に関数をコピーする」だけでは動かなくなっちゃいます (printf を puts に最適化していたがここでは無視).
と, こんな簡単なプログラムですら一筋縄ではいかないことがわかります. libelf... も直接関係ないだろうなぁ....
丁寧なご回答ありがとうございます。
「複数のスレッドが干渉しないように」とは、「複数のスレッドが同じメモリ領域を参照しないように」という意味です。Wr5さんから指摘をいただいた中に、
>ローカル変数なら一般的にスタック上に作成されますし、スレッド毎に別々のスタックが用意されるはずです。
とありましたので、私の杞憂だったようです。グローバル変数をセマフォで制御することは知っていたのですが、ローカル変数についての私の知識不足でした。
実験までしていただいてありがたいのですが、最初の質問から方向性がずれてきている気がするので、新しい補足をお読みいただいた上でなにかご存知のことがありましたら補足をよろしくお願いします。
No.2
- 回答日時:
まずもって, なぜ「鋳型となる関数を用意して、それを別のメモリ上にコピーして実行させる」ことを思いついたのかが謎だったりするわけだが....
この質問文だけでは条件が不足していて, 最低限プロセッサも指定する必要があります. 例えば x86 ならセグメントセレクタ (やそこからつながるページテーブル) も気を付ける必要がありますし, あるいは SPARC だとある種のデータを読み込むときに PC 相対アドレスを使う例がある (だから「関数」だけコピーしても動かないかもしれない) ことも意識しないとダメですからね.
ちょっと #1 に補足しておくと, 今どきのプロセッサを対象とするならほとんどの場合関数内の分岐には相対分岐を使う (だからアドレス修正は不要な) 可能性が高いとは思います. ただし, コンパイラが変わったときにどうなるかは, 当然ですが誰にも保証できません.
余談だけど本来 NX ビットは AMD の表現で Intel では XD ですな.
ご回答ありがとうございます。
確かに質問の条件が不足していました。補足に書きましたような事情で、なるべくアセンブリ言語に深入りしすぎない方法でと思ったのですが、C言語でやろうとするとやはりアセンブリ言語やアーキテクチャに関する知識は不可欠になってしまいますかね・・・
No.1
- 回答日時:
>鋳型となる関数を用意して、それを別のメモリ上にコピーして実行させることを考えています。
今時の環境だと難しいんじゃないですかねぇ……。
OSの挙動に関する知識と、アセンブラの知識が必要そうですが。
ストレージからメモリにロードされた時点で、仮想メモリアドレスに割り当てられますから
関数内の条件分岐などの飛び先アドレスもその際に再割り当てになっているかと。
# 短距離なら相対アドレスジャンプかも知れませんが。
メモリコピーだとこの辺りのアドレスの振り直しが実施されませんよね???
あとは……仮想メモリでの属性として「実行可能」などの属性が設定されていたりするかと思われますが…。
# NXビット…でしたっけ?
迅速なご回答ありがとうございます!
やはり難しいですか・・・
なるほど、条件分岐にもアドレスの再割り当てが行われるのですか。関数アドレスさえ調整すれば大丈夫かと思っていました。メモリの属性はmprotectで変更できるのでコピーすること自体が一番の問題かと思ったのですが、アドレスの再割り当てもかなり厄介そうですね・・・盲点でした(>_<) ご指摘ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラム内から、MIDIファイルの一部分だけを再生する方法 1 2023/02/15 11:08
- CPU・メモリ・マザーボード 「コンピューターのメモリが不足しています」 3 2022/12/15 22:07
- CPU・メモリ・マザーボード 「コンピューターのメモリが不足しています」 5 2022/12/15 10:10
- Excel(エクセル) スプレッドシート 関数で集計したい 2 2023/01/08 17:09
- 統計学 ダミー変数の因子分析について質問です 1 2022/03/27 14:31
- Visual Basic(VBA) vba メモリ節約 3 2022/09/16 21:45
- Windows 10 USBにwindows10をいれて起動する方法 5 2022/04/14 14:29
- PHP 【スプレッドシート】順位のつけ方 2 2022/08/17 13:27
- CPU・メモリ・マザーボード PCのメモリについて質問です 8 2022/10/04 09:35
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAの配列サイズとメモリに関して
-
C言語初心者です。debug assert...
-
FLASH Lite1.1 背景の表示エラ...
-
グローバルメモリについて
-
C言語で、メモリを解放しないで...
-
C言語における再帰呼び出しの...
-
メモリがどんどんなくなっちゃ...
-
PC-98で拡張メモリを使え...
-
動的確保できるメモリ容量
-
初心者過ぎる質問ですが、VRAM...
-
Visul Basicについて
-
VBAで2進数を返すプログラムの...
-
配列がお手上げです。
-
C,C++プログラムの強制終了時の...
-
移動可能メモリ
-
C言語:関数のメモリ上でのサイ...
-
配列データ容量とメモリについて
-
エクセルVBA 大容量CSVファイル...
-
クイックソート
-
「ヒープサイズの設定」て何?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAの配列サイズとメモリに関して
-
C言語で、メモリを解放しないで...
-
メモリ不足
-
メモリが不足しています(VBA)
-
「ヒープサイズの設定」て何?
-
メモリのセグメント違反の解決...
-
バッチファイルでの実行EXEのメ...
-
VB.netでUSBメモリの固有I...
-
EXCEL-VBAにてADOのレコードセ...
-
エクセルのメモリ使用状況/Appl...
-
「memcpy」と「strcpy」について
-
エクセルVBA 大容量CSVファイル...
-
ファイルマッピング関数で失敗
-
大容量のメモリ確保をスワップ...
-
GetAdapterInfoによりマックア...
-
C言語における再帰呼び出しの...
-
C++のCopyFileでメモリが増える
-
メモリを解放しないとどうなる?
-
クリスタルレポートでメモリ不...
-
closeとメモリの開放について
おすすめ情報
Tacosanさんのご指摘の通り、説明不足でした。
プロセッサはIntel x64を想定しています。
「鋳型となる関数を用意して、それを別のメモリ上にコピーして実行させる」ことは、並列計算に興味を持ち、複数のスレッドが干渉し合わないようにスレッドの数だけ関数をコピーして分離する方法、として実験してみようと考えました。OpenMP、OpenMPI、OpenCLなどのライブラリも少し調べたのですが、並列化の方法のニュアンスが違うようなので、可能なところまで自作してみようと思っています。
ご丁寧に回答をいただいたところ申し訳ないのですが、コールやジャンプの依存がある以上、アセンブリ言語の学習のコストは考慮しています。その上で、関数のメモリ上でのサイズを知る方法にはどのようなものがありますか?
この部分だけは調べてもなかなか手がかりがないのです。アセンブリ言語を学べばやり方も自ずとわかりますか?それとも言語処理系やコンパイラ方面の知識を要求されるのでしょうか?情報を得るためにどのようなキーワードが適しているか、などの小さなことでもいいのでご回答いただけないでしょうか?
自己解決しました。
よく考えたらシンボルテーブルの残っている実行ファイルをobjdump -dして別のファイルに保存すれば関数名から場所を特定できますし、不要な部分を削って16進表記の関数を手に入れることができ、サイズもわかります。
メモリの再配置を伴うような複雑な関数は動作しなくなりますが、それを避けるように最適化したコードなら動作するはずです。使用可能な機能、状況は限定的だと思いますが。
私の基礎知識が不足しているせいで何に使えるかもわかりませんが、一応、最初の質問に対する答えにはなっているので書いておきます。たくさんのヒントを与えてくださった回答者の皆様には重ねて感謝いたします。ありがとうございました。