0
1

アプリケーション開発に注力するには

アプリケーション開発に注力するには、下回りが揃っていることが大事。
どんな土台(platform)にもっていっても動かないと意味がない。

<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

リンカ ローダ 

リンカ・ローダ実践開発テクニック―実行ファイルを作成するために必須の技術-COMPUTER-TECHNOLOGY-坂井-弘亮
https://www.amazon.co.jp//dp/4789838072/
https://bookmeter.com/books/630946

参考文献にあるLinkers & Loadersは斜め読みしただけで、自分ではこういう道具は作らないだろうと勝手に思っていた。本書では簡易リンカの作成と、道具の作り方まで有るのがすごい。「setjmp()とlongjmp()」というコラムが1頁に入りきらず4頁になっているのに、節にしていないところも興味深い。

Content
https://shop.cqpub.co.jp/hanbai/books/38/38071.html

目次
第1章 リンカとローダの役割
 1.1 リンカとオブジェクト
 1.2 リンカの仕事
 1.3 実行形式とセクション
 1.4 シンボルと再配置
 1.5 ローダの仕事
 1.6 リンカ・スクリプト
 1.7 スタートアップ・ルーチン
第2章 ELF形式の解析
 2.1 オブジェクト・フォーマット
 2.2 ELF形式の構造
 2.3 使用するサンプル・プログラム
 2.4 ELFヘッダ
 2.5 ABI(Application Binary Interface)
 2.6 セクション名の意味
 2.7 セクション・ヘッダ
 2.8 プログラム・ヘッダ
 2.9 シンボル・テーブル
 2.10 再配置テーブル
 2.11 ELFファイルの解析例
第3章 ライブラリ・アーカイブの解析
 3.1 ライブラリ・アーカイブとは
 3.2 ライブラリ・アーカイブの構造
 3.3 アーカイブの解析例
 3.4 ライブラリ・アーカイブの解析
 3.5 ライブラリ・アーカイブのリンク
 コラム 二つのアーカイブ・フォーマットが混在した場合
 コラム checksymの使いかた
第4章 実験――リンカで遊んでみよう
 4.1 配列とポインタの違い
 4.2 const変数に書き込む
 4.3 グローバル変数をstaticにする
 4.4 シンボルの名前を変更する
 4.5 変数の隠ぺいを階層化する
 4.6 静的変数を再初期化する
 4.7 自動初期化を行う
 4.8 終了時に関数を呼び出す
第5章 リンカ・スクリプトの役割と動作
 5.1 リンカとローダの役割
 5.2 リンカ・スクリプトの役割
第6章 リンカ・スクリプトを使った実験
 6.1 標準のリンカ・スクリプト
 6.2 リンカ・スクリプトの実験
第7章 コマンド・ライン指定による動作の違いとリンカの利用法
 7.1 コマンド・ライン指定の違いによる動作の違い
 7.2 コマンド・ラインによる違いを実験で確かめる
 7.3 重複シンボル問題の解説と解決策
 7.4 リンカの利用の実例――バイナリ・データを挿入する
 コラム そのほかのリンカの利用方法
第8章 ローダの原理と簡易ローダの作成
 8.1 ローダの必要性
 8.2 ローダの概要
 8.3 簡易ローダの原理
 8.4 簡易ローダの作成
 8.5 サンプル・プログラム
 8.6 簡易ローダの実行
第9章 コア・ダンプの解析
 9.1 コア・ダンプとは何か
 9.2 コア・ダンプの詳細
 9.3 中断したプロセスの再開
 9.4 中断と再開の実験
 コラム setjmp()とlongjmp()
第10章 簡易リンカの作成
 10.1 オブジェクト・ファイルとリンカの概要
 10.2 シンボル解決の実際
 10.3 サンプル・プログラム
 10.4 リンカの作成
第11章 共有ライブラリの使い方
 11.1 仮想メモリ
 11.2 位置独立コード
 11.3 ライブラリの作成とインストール
 11.4 共有ライブラリの内部構造
 11.5 動的リンカ
 11.6 動的なライブラリのロード
 コラム 関数ラッパ

LinkerLoaderTech
https://www.cqpub.co.jp/interface/download/2005/02/linker/LinkerLoaderTech.zip

リンカ・ローダ実践開発テクニック 坂井弘亮(1) coding(89) ardump.c
https://qiita.com/kaizen_nagoya/items/2a7bf3050ee6ac662272

リンカ・ローダ実践開発テクニック 坂井弘亮(2) coding(90) binary.c
https://qiita.com/kaizen_nagoya/items/23b985cefc5338677812

リンカ・ローダ実践開発テクニック 坂井弘亮(3) coding(91) combine.c
https://qiita.com/kaizen_nagoya/items/59161e3274270cfd2009

リンカ・ローダ実践開発テクニック 坂井弘亮(4) coding(92) const.c, error(123) docker(174)
https://qiita.com/kaizen_nagoya/items/6f74dbf637a91685d0d1

checksym.c source
https://www.cqpub.co.jp/interface/download/2005/02/linker/checksym.zip

checksym.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <ar.h>
#include <elf.h>
#include <sys/stat.h>
#include <sys/mman.h>

typedef u_int16_t (*rh_t)(u_int16_t *);
typedef u_int32_t (*rw_t)(u_int32_t *);

static u_int32_t read_word_le(u_int32_t *value)
{
  unsigned char *p = (unsigned char *)value;
  return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
}

static u_int32_t read_word_be(u_int32_t *value)
{
  unsigned char *p = (unsigned char *)value;
  return (p[0] << 24 | (p[1] << 16) | (p[2] << 8) | p[3]);
}

static u_int16_t read_half_le(u_int16_t *value)
{
  unsigned char *p = (unsigned char *)value;
  return (p[0] | (p[1] << 8));
}

static u_int16_t read_half_be(u_int16_t *value)
{
  unsigned char *p = (unsigned char *)value;
  return ((p[0] << 8) | p[1]);
}

struct name_list {
  struct name_list *next;
  char *name;
  int size;
  unsigned int flags;
#define NAME_FLAG_NOALLOC (1 << 0)
  char *filename;
  int count;
  int define;
};

static struct name_list *sym_name_list = NULL;
static struct name_list *rel_name_list = NULL;

/* セクション名からセクションヘッダを検索 */
static Elf32_Shdr *get_section(char *filename, rh_t rh, rw_t rw,
			       Elf32_Ehdr *ehdr, char *name)
{
  int i, shnum, shoff, shentsize, nshoff;
  char *head;
  Elf32_Shdr *shdr;
  Elf32_Shdr *nhdr;

  head = (char *)ehdr;
  shnum     = rh(&ehdr->e_shnum);
  shoff     = rw(&ehdr->e_shoff);
  shentsize = rh(&ehdr->e_shentsize);

  nhdr = (Elf32_Shdr *)(head + shoff + shentsize * rh(&ehdr->e_shstrndx));
  nshoff = rw(&nhdr->sh_offset);

  for (i = 0; i < shnum; i++) {
    shdr = (Elf32_Shdr *)(head + shoff + shentsize * i);
    if (!strcmp((char *)(head + nshoff + rw(&shdr->sh_name)), name)) {
      fprintf(stderr, "found %s (%s)\n", name, filename);
      return (shdr);
    }
  }

  fprintf(stderr, "Cannot find %s (%s)\n", name, filename);
  return (NULL);
}

/* シンボルテーブルを総なめして,シンボル名のリストを作成 */
static int make_symbol_table(char *filename, rh_t rh, rw_t rw,
			     Elf32_Ehdr *ehdr, Elf32_Shdr *symtab,
			     Elf32_Shdr *strtab)
{
  int i, shsize, shentsize, shoff, strshoff;
  char *head;
  Elf32_Sym *symp;
  struct name_list *name;

  head = (char *)ehdr;
  if (rw(&symtab->sh_type) != SHT_SYMTAB) {
    fprintf(stderr, "Invalid type. (%d)\n", rw(&symtab->sh_type));
    exit (1);
  }
  if (rw(&symtab->sh_entsize) != sizeof(Elf32_Sym)) {
    fprintf(stderr, "Invalid entry size. (%d)\n", rw(&symtab->sh_entsize));
    exit (1);
  }

  shsize    = rw(&symtab->sh_size);
  shentsize = rw(&symtab->sh_entsize);
  shoff     = rw(&symtab->sh_offset);
  strshoff  = rw(&strtab->sh_offset);

  for (i = 0; i < shsize; i += shentsize) {
    symp = (Elf32_Sym *)(head + shoff + i);
    if (!symp->st_name) continue;
    if (ELF32_ST_BIND(symp->st_info) != STB_GLOBAL) continue;
    if ((ELF32_ST_TYPE(symp->st_info) != STT_NOTYPE) &&
	(ELF32_ST_TYPE(symp->st_info) != STT_OBJECT) &&
	(ELF32_ST_TYPE(symp->st_info) != STT_FUNC))
      continue;
    if (!symp->st_size) continue;

    name = malloc(sizeof(*name));
    name->next = sym_name_list;
    name->name = strdup(head + strshoff + rw(&symp->st_name));
    name->size = rw(&symp->st_size);
    name->flags = 0;
    if (rh(&symp->st_shndx) == SHN_COMMON)
      name->flags |= NAME_FLAG_NOALLOC;
    name->filename = strdup(filename);
    name->count = 0;
    name->define = 1;
    sym_name_list = name;
  }

  return (0);
}

/* 再配置テーブルを総なめして,シンボル名のリストを作成 */
static int make_reltxt_table(char *filename, rh_t rh, rw_t rw,
			     Elf32_Ehdr *ehdr, Elf32_Shdr *reltxt,
			     Elf32_Shdr *symtab, Elf32_Shdr *strtab)
{
  int i, shsize, shentsize, shoff, symshoff, symshentsize, strshoff;
  char *head;
  Elf32_Sym *symp;
  Elf32_Rel *relp;
  struct name_list *name;

  head = (char *)ehdr;
  if ((rw(&reltxt->sh_type) != SHT_REL) &&
      (rw(&reltxt->sh_type) != SHT_RELA)) {
    fprintf(stderr, "Invalid type. (%d)\n", rw(&reltxt->sh_type));
    exit (1);
  }

  shsize       = rw(&reltxt->sh_size);
  shentsize    = rw(&reltxt->sh_entsize);
  shoff        = rw(&reltxt->sh_offset);
  symshoff     = rw(&symtab->sh_offset);
  symshentsize = rw(&symtab->sh_entsize);
  strshoff     = rw(&strtab->sh_offset);

  for (i = 0; i < shsize; i += shentsize) {
    relp = (Elf32_Rel *)(head + shoff + i);
    symp = (Elf32_Sym *)(head + symshoff +
			 (symshentsize * ELF32_R_SYM(rw(&relp->r_info))));
    if (!symp->st_name) continue;

    name = malloc(sizeof(*name));
    name->next = rel_name_list;
    name->name = strdup(head + strshoff + rw(&symp->st_name));
    name->size = 0;
    name->flags = 0;
    name->filename = strdup(filename);
    name->count = 0;
    name->define = 0;
    rel_name_list = name;
  }

  return (0);
}

static void read_reltxt(char *filename, rh_t rh, rw_t rw, Elf32_Ehdr *ehdr,
			Elf32_Shdr *symtab, Elf32_Shdr *strtab,
			char *section_name)
{
  Elf32_Shdr *reltxt;
  reltxt = get_section(filename, rh, rw, ehdr, section_name);
  if (reltxt) {
    make_reltxt_table(filename, rh, rw, ehdr, reltxt, symtab, strtab);
  }
}

static int readelf(char *filename, char *head)
{
  Elf32_Ehdr *ehdr;
  Elf32_Shdr *symtab;
  Elf32_Shdr *strtab;
  rh_t rh;
  rw_t rw;

  ehdr = (Elf32_Ehdr *)head;
  if (!IS_ELF(*ehdr)) {
    fprintf(stderr, "This is not ELF file. (%s)\n", filename);
    return (1);
  }

  if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
    fprintf(stderr, "unknown class. (%d)\n", (int)ehdr->e_ident[EI_CLASS]);
    return (1);
  }

  switch (ehdr->e_ident[EI_DATA]) {
  case ELFDATA2MSB:
    rh = read_half_be;
    rw = read_word_be;
    break;
  case ELFDATA2LSB:
    rh = read_half_le;
    rw = read_word_le;
    break;
  default:
    fprintf(stderr, "unknown endian. (%d)\n", (int)ehdr->e_ident[EI_DATA]);
    return (1);
  }

  if ((rh(&ehdr->e_type) != ET_EXEC) && (rh(&ehdr->e_type) != ET_REL)) {
    fprintf(stderr, "unknown type. (%d)\n", (int)rh(&ehdr->e_type));
    return (1);
  }

  symtab = get_section(filename, rh, rw, ehdr, ".symtab");
  strtab = get_section(filename, rh, rw, ehdr, ".strtab");

  if (symtab && strtab) {
    make_symbol_table(filename, rh, rw, ehdr, symtab, strtab);

    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rel.text");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rela.text");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rel.data");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rela.data");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rel.rodata");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rela.rodata");
#if 0
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rel.stab");
    read_reltxt(filename, rh, rw, ehdr, symtab, strtab, ".rela.stab");
#endif
  }

  return (0);
}

static int get_value(const char *s, int len)
{
  char buffer[20];
  memcpy(buffer, s, len);
  buffer[len] = '\0';
  return (atoi(buffer));
}

static char *get_string(const char *s, int maxlen)
{
  char *buffer;
  int len;
  for (len = 0; s[len] != ' ' && s[len] != '/' && s[len] != '\0'; len++) {
    if (maxlen && (len >= maxlen)) break;
  }
  buffer = malloc(len + 1);
  memcpy(buffer, s, len);
  buffer[len] = '\0';
  return (buffer);
}

static int readar(char *filename, char *head, int size)
{
  int offset, soffset;
  char *f, *f2;
  struct ar_hdr *arhdr;
  struct ar_hdr *nhdr;

  nhdr = NULL;
  for (offset = SARMAG; offset < size;) {
    arhdr = (struct ar_hdr *)(head + offset);
    if ((arhdr->ar_name[0] == '/') &&
	(arhdr->ar_name[1] == ' ')) {
      fprintf(stderr, "symbol table found.\n");
    } else if ((arhdr->ar_name[0] == '/') &&
	       (arhdr->ar_name[1] == '/')) {
      fprintf(stderr, "string table found.\n");
      nhdr = arhdr;
    } else {
      f = NULL;
      if (arhdr->ar_name[0] == '/') {
        soffset = get_value(&(arhdr->ar_name[1]), sizeof(arhdr->ar_name) - 1);
        if (nhdr == NULL) {
          fprintf(stderr, "yet not found string table.\n");
        } else {
	  f = get_string((char *)nhdr + sizeof(struct ar_hdr) + soffset, 0);
	}
      } else {
	f = get_string(arhdr->ar_name, sizeof(arhdr->ar_name));
      }
      if (f) {
	fprintf(stderr, "found file %s in %s. ", f, filename);
	if (IS_ELF(*(Elf32_Ehdr *)((char *)arhdr + sizeof(struct ar_hdr)))) {
	  fprintf(stderr, "ELF file reading...\n");
	  f2 = malloc(strlen(f) + strlen(filename) + 4);
	  sprintf(f2, "%s (%s)", f, filename);
	  readelf(f2, (char *)arhdr + sizeof(struct ar_hdr));
	  free(f2);
	} else {
	  fprintf(stderr, "not ELF file.\n");
	}
	free(f);
      }
    }
    offset +=
      sizeof(struct ar_hdr)
      + get_value(arhdr->ar_size, sizeof(arhdr->ar_size));
    offset = ((offset + 1) / 2) * 2;
  }

  return (0);
}

int main(int argc, char *argv[])
{
  int i, fd, size, sizesum;
  char *filename;
  struct stat sb;
  char *head;
  struct name_list *n1;
  struct name_list *n2;
  struct name_list **np;

  for (i = 1; i < argc; i++) {
    filename = argv[i];
    fd = open(filename, O_RDONLY);
    if (fd < 0) continue;
    fstat(fd, &sb);
    size = sb.st_size;
    head = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if (!memcmp(head, ARMAG, SARMAG)) {
      fprintf(stderr, "%s is AR file. reading...\n", filename);
      readar(filename, head, size);
    } else if (IS_ELF(*(Elf32_Ehdr *)head)) {
      fprintf(stderr, "%s is ELF file. reading...\n", filename);
      readelf(filename, head);
    } else {
      fprintf(stderr, "Unknown file format. (%s)\n", filename);
      exit (1);
    }

    munmap(head, sb.st_size);
    close(fd);
  }

  fprintf(stderr, "collecting... ");
  for (n1 = sym_name_list; n1; n1 = n1->next) {
    for (np = &(n1->next); *np;) {
      n2 = *np;
      if (!strcmp(n1->name, n2->name)) {
	printf("collect duplicate symbols %s (%s, %s)\n",
	       n1->name, n1->filename, n2->filename);
	free(n1->filename);
	n1->filename = strdup("(duplicate)");
	n1->define += n2->define;
	*np = n2->next;
	free(n2->name);
	free(n2->filename);
	free(n2);
      } else {
	np = &(n2->next);
      }
    }
  }
  fprintf(stderr, "OK.\n");

  fprintf(stderr, "counting... ");
  for (n1 = rel_name_list; n1; n1 = n1->next) {
    for (n2 = sym_name_list; n2; n2 = n2->next) {
      if (!strcmp(n1->name, n2->name)) {
	(n2->count)++;
	break;
      }
    }
  }
  fprintf(stderr, "OK.\n");

  printf("Defined symbol list:\n");
  for (n1 = sym_name_list; n1; n1 = n1->next) {
    printf("%s (Ref:%d, Size:%d)(%s)\n", n1->name, n1->count, n1->size,
	   (n1->flags & NAME_FLAG_NOALLOC) ? "noalloc" : "alloc");
  }

  printf("\nReferenced symbol list:\n");
  for (n1 = rel_name_list; n1; n1 = n1->next) {
    printf("%s\n", n1->name);
  }

  printf("\nDuplicated symbol list:\n");
  sizesum = 0;
  for (n1 = sym_name_list; n1; n1 = n1->next) {
    if (n1->define > 1) {
      printf("%s (Duplicate:%d)\n", n1->name, n1->define);
    }
  }

  printf("\nUnreferenced symbol list:\n");
  sizesum = 0;
  for (n1 = sym_name_list; n1; n1 = n1->next) {
    if (n1->count == 0) {
      printf("%s:\t%s (Size:%d)(%s)\n", n1->filename, n1->name, n1->size,
	     (n1->flags & NAME_FLAG_NOALLOC) ? "noalloc" : "alloc");
      sizesum += n1->size;
    }
  }

  printf("\nUnreferenced symbols size sum: %d byte\n", sizesum);

  exit (0);
}

event URL

502: Bad Gateway
リクエストの処理に時間がかかっています。しばらくしてから再度お試しください。
このページが繰り返し表示される場合は
support@qiita.comまでご連絡ください。
なお、Twitterにて最新の情報を配信しております。

ログインせずにアクセスすると表示する。理由は不明。

関連資料

私が効果を確認した「小川メソッド」
https://qiita.com/kazuo_reve/items/a3ea1d9171deeccc04da

自己記事一覧

Qiitaの記事に3段階または5段階で到達するための方法
https://qiita.com/kaizen_nagoya/items/6e9298296852325adc5e

物理記事 上位100
https://qiita.com/kaizen_nagoya/items/66e90fe31fbe3facc6ff

量子(0) 計算機, 量子力学
https://qiita.com/kaizen_nagoya/items/1cd954cb0eed92879fd4

数学関連記事100
https://qiita.com/kaizen_nagoya/items/d8dadb49a6397e854c6d

統計(0)一覧
https://qiita.com/kaizen_nagoya/items/80d3b221807e53e88aba

品質一覧
https://qiita.com/kaizen_nagoya/items/2b99b8e9db6d94b2e971

言語・文学記事 100
https://qiita.com/kaizen_nagoya/items/42d58d5ef7fb53c407d6

医工連携関連記事一覧
https://qiita.com/kaizen_nagoya/items/6ab51c12ba51bc260a82

自動車 記事 100
https://qiita.com/kaizen_nagoya/items/f7f0b9ab36569ad409c5

通信記事100
https://qiita.com/kaizen_nagoya/items/1d67de5e1cd207b05ef7

日本語(0)一欄
https://qiita.com/kaizen_nagoya/items/7498dcfa3a9ba7fd1e68

英語(0) 一覧
https://qiita.com/kaizen_nagoya/items/680e3f5cbf9430486c7d

転職(0)一覧
https://qiita.com/kaizen_nagoya/items/f77520d378d33451d6fe

仮説(0)一覧(目標100現在40)
https://qiita.com/kaizen_nagoya/items/f000506fe1837b3590df

音楽 一覧(0)
https://qiita.com/kaizen_nagoya/items/b6e5f42bbfe3bbe40f5d

@kazuo_reve 新人の方によく展開している有益な情報」確認一覧
https://qiita.com/kaizen_nagoya/items/b9380888d1e5a042646b

Qiita(0)Qiita関連記事一覧(自分)
https://qiita.com/kaizen_nagoya/items/58db5fbf036b28e9dfa6

鉄道(0)鉄道のシステム考察はてっちゃんがてつだってくれる
https://qiita.com/kaizen_nagoya/items/26bda595f341a27901a0

安全(0)安全工学シンポジウムに向けて: 21
https://qiita.com/kaizen_nagoya/items/c5d78f3def8195cb2409

一覧の一覧( The directory of directories of mine.) Qiita(100)
https://qiita.com/kaizen_nagoya/items/7eb0e006543886138f39

Ethernet 記事一覧 Ethernet(0)
https://qiita.com/kaizen_nagoya/items/88d35e99f74aefc98794

Wireshark 一覧 wireshark(0)、Ethernet(48)
https://qiita.com/kaizen_nagoya/items/fbed841f61875c4731d0

線網(Wi-Fi)空中線(antenna)(0) 記事一覧(118/300目標)
https://qiita.com/kaizen_nagoya/items/5e5464ac2b24bd4cd001

OSEK OS設計の基礎 OSEK(100)
https://qiita.com/kaizen_nagoya/items/7528a22a14242d2d58a3

Error一覧 error(0)
https://qiita.com/kaizen_nagoya/items/48b6cbc8d68eae2c42b8

++ Support(0) 
https://qiita.com/kaizen_nagoya/items/8720d26f762369a80514

Coding(0) Rules, C, Secure, MISRA and so on
https://qiita.com/kaizen_nagoya/items/400725644a8a0e90fbb0

プログラマによる、プログラマのための、統計(0)と確率のプログラミングとその後
https://qiita.com/kaizen_nagoya/items/6e9897eb641268766909

なぜdockerで機械学習するか 書籍・ソース一覧作成中 (目標100)
https://qiita.com/kaizen_nagoya/items/ddd12477544bf5ba85e2

言語処理100本ノックをdockerで。python覚えるのに最適。:10+12
https://qiita.com/kaizen_nagoya/items/7e7eb7c543e0c18438c4

プログラムちょい替え(0)一覧:4件
https://qiita.com/kaizen_nagoya/items/296d87ef4bfd516bc394

Python(0)記事をまとめたい。
https://qiita.com/kaizen_nagoya/items/088c57d70ab6904ebb53

官公庁・学校・公的団体(NPOを含む)システムの課題、官(0)
https://qiita.com/kaizen_nagoya/items/04ee6eaf7ec13d3af4c3

「はじめての」シリーズ  ベクタージャパン 
https://qiita.com/kaizen_nagoya/items/2e41634f6e21a3cf74eb

AUTOSAR(0)Qiita記事一覧, OSEK(75)
https://qiita.com/kaizen_nagoya/items/89c07961b59a8754c869

プログラマが知っていると良い「公序良俗」
https://qiita.com/kaizen_nagoya/items/9fe7c0dfac2fbd77a945

LaTeX(0) 一覧 
https://qiita.com/kaizen_nagoya/items/e3f7dafacab58c499792

自動制御、制御工学一覧(0)
https://qiita.com/kaizen_nagoya/items/7767a4e19a6ae1479e6b

Rust(0) 一覧 
https://qiita.com/kaizen_nagoya/items/5e8bb080ba6ca0281927

100以上いいねをいただいた記事16選
https://qiita.com/kaizen_nagoya/items/f8d958d9084ffbd15d2a

小川清最終講義、最終講義(再)計画, Ethernet(100) 英語(100) 安全(100)
https://qiita.com/kaizen_nagoya/items/e2df642e3951e35e6a53

<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>
This article is an individual impression based on my individual experience. It has nothing to do with the organization or business to which I currently belong.

文書履歴(document history)

ver. 0.01 初稿  20240706

最後までおよみいただきありがとう4ざいました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1